Document-App (wie iTunes / iPhoto), NSDocument und CoreData

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • Document-App (wie iTunes / iPhoto), NSDocument und CoreData

    Hi Leute,

    ich hab da mal wieder ein paar Fragen. Ich bin (immer noch) dabei, eine Cocoa Anwendung für OS X zu entwickeln. Bin zwar nicht neu in der Programmierung, aber eben neu im Entwickeln unter OS X. Hab nun schon die ein oder andre Erfahrung gemacht und mittlerweile auch ein Buch gekauft - so ganz ohne geht's zwar schon, aber schwerer als notwendig. Das aktuelle Projekt ist auch explizit als Lernprojekt gedacht, dass nachher aber trotzdem produktiv eingesetzt werden soll. So kam es auch, dass ich den ersten Entwurf komplett über Bord geschmissen und mit dem bis dato gelernten neu angefangen hab. Soviel zur Vorgeschichte.

    Die App soll ähnlich iTunes / iPhoto eine Datenverwaltung darstellen, die nur eine einzige "Datenbank" hat. Die Datenbank ist ein File-Bundle (wie z. B. bei iPhoto). In diesem File-Bundle liegt mein SQL-Store für CoreData und andere, zusätzliche Dokumente / Dateien. Nun zu meinen Fragen:
    • Ist es prinzipiell richtig, das ganze mit NSDocument zu realisieren, oder ist das ein "Overkill" bzw. der falsche Ansatz? Anders kann ich aber wohl keine Dateiendung als Datei für meine App registrieren. Zumindest wüsste ich nicht wie.
    • Wie kann ich dafür sorgen, dass beim Start der App immer meine Datenbank per NSDocument geöffnet wird? I. d. R. passt das, hatte es beim Debuggen aber auch das ein oder andere mal, dass mein Fenster mit den Daten erst erschienen ist, wenn ich auf das App-Icon geklickt hab. (Bin mir jetzt im Moment gar nicht sicher, ob das Fenster vielleicht einfach im Hintergrund geöffnet wurde und Xcode davor lag).
    • Wenn ich schon CoreData verwende, wäre NSPersistentDocument vielleicht die bessere Wahl (mach das ganze Core-Date Verwaltungszeugs momentan "per Hand", was zum lernen freilich praktischer ist). Wie aber kann ich dem NSPersistentDocument mitteilen, dass es für den Store bitte die Datei X im Verzeichnis Y und dem Format Z (in meinem Fall SQL) verwenden soll? Oder muss ich hier configurePersistentStoreCoordinatorForURL
      überschreiben und den PersistentStoreCoordinator selbst erstellen?
    • Autosave wäre ja ganz nett, um Änderungen in CoreData zeitnah ab zu speichern. Geht das auch ohne dass der User den Dateinahmen im Fenstertitel ändern kann? Das würde hier nämlich überhaupt kein Sinn machen.
    Ok, soviel erstmal dazu. Danke schonmal und happy coding

    Marc
  • Eine Document-Based Application wäre eigentlich falsch, da man damit ja mehrere "Dokumente" öffnen und bearbeiten kann. iTunes und iPhoto sind ja auch keine Document-Based Applications. ;)

    Erstelle mal ein neues Projekt mit Xcode mit dem Template "OS X" > "Application" > "Cocoa Application" und wähle als Optionen nur "Use Core Data", also ohne "Create Document-Based Application".

    Dann solltest Du eine App mit nur einem "Document" bzw. Datenpool haben.
  • Nun, das Problem dabei war immer, dass beim Doppelklick auf die zugeordnete Datei meine App sich meldete und motzte, dass sie keine Ahnung hätte, was sie damit anfangen solle. Deswegen dachte ich, ich müsse NSDocument verwenden, da kam die Meldung nämlich nicht. Nun - nach deinem Kommentar hab ich nochmal nachgefasst und geforscht und kam darauf, dass es da ne nette NSApplicationDelegate Geschichte gibt, die ich einfach implementierne musste. Tja, ab und an mal genau die Protokolle und deren Docus anschauen wirkt schon Wunder. :-/

    Jetzt hab ich aber ein anderes Problem: Ich versuche im Fall, dass der Anwender im Finder auf die "Datei" doppelklickt, in application:openFile: meinen Datenbestand zu laden. Tritt dabei ein Fehler auf, wird eine Meldung ausgegeben und die App beendet. So sieht das ganze aus:

    Quellcode

    1. - (BOOL)application:(NSApplication *)sender openFile:(NSString *)filename
    2. {
    3. self.database = [MyDatabase sharedInstance];
    4. if (![self.database open:[NSURL fileURLWithPath:filename isDirectory:YES]]) {
    5. NSAlert *alert = [NSAlert alertWithError:self.database.lastError];
    6. [alert runModal];
    7. [[NSApp sharedApplication] terminate:nil];
    8. return NO;
    9. }
    10. return YES;
    11. }
    Alles anzeigen

    Soweit so gut - bis auf die Tatsache, dass im Falle eines Fehlers und des damit verbundenen Aufrufs von "[[NSApp sharedApplication] terminate:nil]" die App zwar beendet, vorher jedoch application:openFile: nochmal aufgerufen wird. Dass da was durcheinander kommt, ist mir schon klar. Denn ich zieh der App sozusagen den Stuhl unterm Gesäß weg...

    Wie kann ich denn sinnvoll das Programm, welches sich quasi gerade beim Initialisieren und Laden befindet, direkt wieder beenden?

    Gruß Marc
  • Äh, was spricht gegen CFBundleDocumentTypes? Wenn ich das in der plist meiner App verwende, wird im Finder bei einer entsprechenden Dateiendung ebenfalls das Icon meiner App angezeigt. Mach ich nen Doppelklick drauf, wird meine App gestartet und application:openFile: aufgerufen. Wenn ich mit Rechtsklick auf die Datei gehe (die letztlich ein Verzeichnis mit der entsprechenden Endung ist), wird ebenfalls meine App angezeigt.

    Wo liegt also der Unterschieb duz UTImportetTypeDeclarations? (Hab mich damit bisher nicht beschäftigt).

    Gruß Marc