sqlite3 Datenbank soll bei update über iTunes überschrieben werden

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

    • sqlite3 Datenbank soll bei update über iTunes überschrieben werden

      Hallo,

      ich habe folgendes Problem, bei dem ich einfach nicht weiter komme:
      Meine App nutzt eine sqlite3-Datenbank (read-only), die mit jedem Update der App über iTunes komplett überschrieben werden soll.
      In einem Forum habe ich gelesen, daß bei einem Update der App über iTunes das alte App-Bundle uninstalliert wird und das neue App-Bundle installiert wird, aber die User Daten, die mit dem App-Bundle verbunden sind, bleiben intakt. Mit jedem Aufruf der App sollte der hier dargestellte Code die SQLite Datenbank aus dem App-Bundle in die User-Datenbank kopieren und damit die alte Datenbank überschreiben.

      Im Simulator funktioniert das gut, aber über iTunes wird die Datenbank nicht aktualisiert, sondern die alte Datenbank bleibt bestehen.

      Frage 1: Was mache ich falsch ?
      Frage 2: Kann es sein, daß ich die alte Datenbank im User-Filesystem zunächst löschen muss? Wenn ja, ist dies der richtige Befehl dazu und wo muss ich diesen in meinen Code einfügen?
      [fileManager removeFileAtPath:databasePath handler:nil];

      Frage 3: Muss ich [fileManager release]; ausführen?

      Frage 4: Wo muss die sqlite-Datenbank in dem Xcode-Projekt abgelegt werden? Im Root-Verzeichnis oder im Ressourcen-Verzeichnis?

      Im SQLite App Delegate.m habe ich folgenden Code verwendet, es gibt weder eine Fehlermeldung, noch eine Warnung.


      Quellcode

      1. @implementation SQLiteTutorialAppDelegate
      2. @synthesize window;
      3. @synthesize viewController;
      4. - (void)applicationDidFinishLaunching:(UIApplication *)application {
      5. [self copyDatabaseIfNeeded];
      6. [window addSubview:viewController.view];
      7. [window makeKeyAndVisible];
      8. }
      9. - (void) copyDatabaseIfNeeded {
      10. // Check if the SQL database has already been saved to the users phone, if not then copy it over"
      11. // Create a FileManager object, we will use this to check the status of the database and to copy it over if required"
      12. NSFileManager *fileManager = [NSFileManager defaultManager]; NSError *error; NSString *dbPath = [self getDBPath];
      13. // Check if the database has already been created in the users filesystem
      14. // BOOL success = [fileManager fileExistsAtPath:dbPath];
      15. // If the database already exists then return without doing anything
      16. // if(!success) {
      17. // If not then proceed to copy the database from the application to the users filesystem
      18. [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"Foemidb4.sqlite"];
      19. // Copy the database from the package to the users filesystem
      20. // [fileManager removeFileAtPath:dbPath handler:nil];
      21. BOOL success = [fileManager copyItemAtPath:defaultDBPath toPath:dbPath error:&error];
      22. if (!success) NSAssert1(0, @"Failed to create writable database file with message '%@'.", [error localizedDescription]);
      23. // [fileManager release];
      24. // }
      25. @end
      26. }
      Alles anzeigen



      Wäre super, wenn ihr eine Lösung findet !
      Danke,
      Alexander
    • Hi,
      das ist das falsche Forum, sollte in iOS rein.



      "Frage 3: Muss ich [fileManager release]; ausführen?"
      Nein.

      "
      Frage 4: Wo muss die sqlite-Datenbank in dem Xcode-Projekt abgelegt werden? Im Root-Verzeichnis oder im Ressourcen-Verzeichnis?"
      Egal. Aber besser in Resources, da hierdurch eine Ordnung gegeben ist.
      Resources ist kein Ordner, sondern eine Group.
      Alles landet im Root-Verzeichnis der App. (myApp.app/).

      Da bereits eine DB sich an dem Path befindet wirds nichts kopiert (Zeile 19).
      Du musst eine Versionsnummer der DB mitführen.
      Wenn sich die DB-Versin ändert kopier die DB.

      So:

      Quellcode

      1. #define DB_VERSION 1 // Bei neuer DB - Version einfach erhöhen.
      2. @implementation SQLiteTutorialAppDelegate
      3. @synthesize window;
      4. @synthesize viewController;
      5. - (void)applicationDidFinishLaunching:(UIApplication *)application {
      6. [self copyDatabaseIfNeeded];
      7. [window addSubview:viewController.view];
      8. [window makeKeyAndVisible];
      9. }
      10. - (void) copyDatabaseIfNeeded {
      11. // Check if the SQL database has already been saved to the users phone, if not then copy it over"
      12. // Create a FileManager object, we will use this to check the status of the database and to copy it over if required"
      13. NSFileManager *fileManager = [NSFileManager defaultManager];
      14. NSError *error;
      15. NSString *dbPath = [self getDBPath];
      16. // Check if the database has already been created in the users filesystem
      17. BOOL copyDB = [fileManager fileExistsAtPath:dbPath];
      18. NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
      19. int dbVersion = [defaults integerForKey:@"DBVersion"];
      20. copyDB &= dbVersion != DB_VERSION;
      21. // If the database already exists then return without doing anything
      22. if(!copyDB) {
      23. // If not then proceed to copy the database from the application to the users filesystem
      24. [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"Foemidb4.sqlite"];
      25. // Copy the database from the package to the users filesystem
      26. [fileManager removeItemAtPath:dbPath error:nil];
      27. BOOL success = [fileManager copyItemAtPath:defaultDBPath toPath:dbPath error:&error];
      28. if (!success) NSAssert1(0, @"Failed to create writable database file with message '%@'.", [error localizedDescription]);
      29. else {
      30. [defaults setInteger:DB_VERSION forKey:@"DBVersion"];
      31. [defaults synchronize];
      32. }
      33. }
      34. @end
      Alles anzeigen
      Inos ist ein Gott aus Gothic, dem Spiel.
    • "Noch eine Frage: Wie komme ich auf defaultDBPath?"
      Wenn du die SQLite-Datei in die Gruppe Ressources deines Projektes abgelegt hast, erhälst du den Path zu deiner DB, die angenommen meineDB.sqlite heißt, z.B. mittels:

      Quellcode

      1. NSString *defaultPath= [[NSBundle mainBundle] pathForResource:@"meineDB" ofType:@"sqlite"];


      und speicherst diese im "Documents" - Verzeichnis deiner App. ab:

      Quellcode

      1. - (NSString *) getDBPath {
      2. NSArray *paths= NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
      3. return [[paths objectAtIndex:0] stringByAppendingPathComponent:@"meineDB.sqlite"];
      4. }
      Inos ist ein Gott aus Gothic, dem Spiel.
    • User Defaults

      Vielen Dank, das hat gut funktioniert. Die App ist bereits auf den Endgeräten der User installiert, momentan noch ohne die DB-Settings in den User-Defaults. Wenn ich den von Dir vorgeschlagenen Code nun anwende und die DB-Version abfrage, ist der Befehl noch nicht ausgeführt worden:


      Quellcode

      1. [defaults setInteger:DB_VERSION forKey:@"DBVersionFoemi"];




      D.h. die DB-Version ist in den User-Defaults noch nicht angelegt worden.
      Könnte dies bei einem Update der App zu einem Absturz führen?
      :whistling:
    • Danke allen,
      ich habe das so umgesetzt und es funktioniert auch.
      Angenommen, der Nutzer löscht nun die App auf seinem iPhone und installiert diese neu. Der "alte" Eintrag in den User defaults ist dann noch immer vorhanden und zeigt an, dass die Datenbank schon kopiert wurde, nehme ich an?
      Das hiesse, die Datenbank wird bei Neuinstallation nicht mehr kopiert?
      Grüße
      klawitter
    • SQLlite Datenbank wird nach Installation auf dem iPhone nicht aus dem Bundle geladen?

      Hallo Liebe Spezialisten,

      ich habe Eure Tips umgesetzt. In den meisten Fällen (99%) wird bei einem Update der App in iTunes die SQLite Datenbank korrekt gelöscht und aus dem Package neu geladen. In 1% der Fälle klappt dies jedoch nicht. Offenbar wird die Datenbank dann nicht aus dem Package geladen und installiert. Ich bin total ratlos. Hier ist der Code, den ich in der Datei SQLAppdelegate.m abgelegt habe:

      Quellcode

      1. #define DB_VERSION 1 // Bei neuer DB - Version einfach erhöhen.
      2. #import "SQLiteTutorialAppDelegate.h"
      3. #import "RootViewController.h"
      4. @implementation SQLiteTutorialAppDelegate
      5. @synthesize window;
      6. @synthesize viewController;
      7. - (void)applicationDidFinishLaunching:(UIApplication *)application {
      8. [self copyDatabaseIfNeeded];
      9. [window addSubview:viewController.view];
      10. [window makeKeyAndVisible];
      11. }
      12. - (void) copyDatabaseIfNeeded {
      13. // Check if the SQL database has already been saved to the users phone, if not then copy it over"
      14. // Create a FileManager object, we will use this to check the status of the database and to copy it over if required"
      15. NSFileManager *fileManager = [NSFileManager defaultManager];
      16. NSError *error;
      17. NSString *dbPath = [self getDBPath];
      18. // NSString *defaultDBPath= [[NSBundle mainBundle] pathForResource:@"Foemidb4" ofType:@"sqlite"];
      19. NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"Foemidb4.sqlite"];
      20. // Check if the database has already been created in the users filesystem
      21. BOOL copyDB = [fileManager fileExistsAtPath:dbPath];
      22. NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
      23. int dbVersion = [defaults integerForKey:@"DBVersFoemVoll"];
      24. copyDB &= dbVersion != DB_VERSION;
      25. // If the database already exists then return without doing anything
      26. if(!copyDB) {
      27. // If not then proceed to copy the database from the application to the users filesystem
      28. [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"Foemidb4.sqlite"];
      29. // Copy the database from the package to the users filesystem
      30. [fileManager removeItemAtPath:dbPath error:nil];
      31. BOOL success = [fileManager copyItemAtPath:defaultDBPath toPath:dbPath error:&error];
      32. if (!success) NSAssert1(0, @"Failed to create writable database file with message '%@'.", [error localizedDescription]);
      33. else {
      34. [defaults setInteger:DB_VERSION forKey:@"DBVersFoemVoll"];
      35. [defaults synchronize];
      36. }
      37. }
      38. }
      39. - (NSString *) getDBPath {
      40. NSArray *paths= NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
      41. return [[paths objectAtIndex:0] stringByAppendingPathComponent:@"Foemidb4.sqlite"];
      42. }
      43. @end
      Alles anzeigen


      Habe ich irgend etwas nicht beachtet?

      Beste Grüße
      klawitter

      ?(
    • Ich kenne das Problem aus einer anderen Situation. Das hat mir echt Kopfzerbrechen bereitet. Ich habe in einer meiner Apps auch eine Datei beim Start der App neu aus dem INET gelesen und wollte dann die lokale auf der App da mit überschreiben. Das hat in 99% der Fälle geklappt aber manchmal eben nicht. Im Endeffekt lag es daran, dass die zu überschreibende Datei noch einen Lock hatte. Wenn der User sein iPhone komplett ausgeschaltet hat, dann ging es wieder. Macht aber nunmal keiner. Die Dinger laufen ja 24/7. Woher dieser Lock kam, kann ich nicht sagen. Unter irgendwelchen Umständen wurde die Datei wohl nicht geschlossen, obwohl ich alles zigmal kontrolliert hatte.

      Eventuell hast du genau dieses Problem auch ?

      Gruß

      Claus
      2 Stunden Try & Error erspart 10 Minuten Handbuchlesen.

      Pre-Kaffee-Posts sind mit Vorsicht zu geniessen :)
    • Thallius schrieb:

      Ich kenne das Problem aus einer anderen Situation. Das hat mir echt Kopfzerbrechen bereitet. Ich habe in einer meiner Apps auch eine Datei beim Start der App neu aus dem INET gelesen und wollte dann die lokale auf der App da mit überschreiben. Das hat in 99% der Fälle geklappt aber manchmal eben nicht. Im Endeffekt lag es daran, dass die zu überschreibende Datei noch einen Lock hatte. Wenn der User sein iPhone komplett ausgeschaltet hat, dann ging es wieder. Macht aber nunmal keiner. Die Dinger laufen ja 24/7. Woher dieser Lock kam, kann ich nicht sagen. Unter irgendwelchen Umständen wurde die Datei wohl nicht geschlossen, obwohl ich alles zigmal kontrolliert hatte.

      Eventuell hast du genau dieses Problem auch ?

      Gruß

      Claus
      Hallo Claus,


      das hört sich fast danach an. Leider fühlen sich genau diese User berufen, eine miserable Bewertung der App zu schreiben, die dieses Problem haben. Die anderen 99% rühren sich nicht.

      Gibt es keine Lösung für dieses Problem? Wie kann ich den Lock entfernen?


      Beste Grüße
      Alexander
    • Thallius schrieb:


      Scheiß doch einfach drauf und nenn deine neue Datenbank anders. Dann kannst du immer noch die alte versuchen zu löschen um den Speicher zu sparen, aber wenn es nicht geht pech für den User. Wird er eh nicht merken.

      Gruß

      Claus
      Hallo Claus, wie muss ich den Code denn anpassen, wenn ich Deinen Vorschlag umsetze (die Datenbank umbenennen bekomme ich hin) ?
    • Thallius schrieb:

      Scheiß doch einfach drauf und nenn deine neue Datenbank anders. Dann kannst du immer noch die alte versuchen zu löschen um den Speicher zu sparen, aber wenn es nicht geht pech für den User. Wird er eh nicht merken.

      Gruß

      Claus

      Thallius schrieb:

      Naja du nennst sie einfach nicht Foemidb4 sondern Foemidb5. Das wars.

      Gruß

      Claus
      Ja, vielen Dank. Aber wie löscht man die alte...?
    • Fehlermeldung

      ich habe die Datenbank nun umgenannt in Foemidb5.sqlite, beim Build gibt es jedoch eine Fehlermeldung, dich ich mir nicht erklären kann:

      ! Copy Foemidb4.sqlite
      pbxcp: Foemidb4.sqlite: No such file directory.

      CpResource build/Distribution-iphonesimulator/Fm11.app/Foemidb4.sqlite Foemidb4.sqlite

      cd /Users/ags/Apps_freigegeben/FmV2

      setenv PATH "/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin:/Developer/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin"

      /Developer/Library/PrivateFrameworks/DevToolsCore.framework/Resources/pbxcp -exclude .DS_Store -exclude CVS -exclude .svn -exclude .git -strip-debug-symbols -resolve-src-symlinks /Users/ags/Apps_freigegeben/FmV2/Foemidb4.sqlite /Users/ags/Apps_freigegeben/FmV2/build/Distribution-iphonesimulator/Fm11.app

      Dies erscheint, obwohl ich im Code alles umgenannt habe, Clean ausgeführt und den Build-Ordner gelöscht!
      Wo kommt der alte Datenbankname her?
    • DB wird nicht aus dem Bundle installiert?

      Ja, danke, er hatte sich in der Gruppe "others" versteckt.

      Nachdem ich einen User gesprochen habe, ist das Problem offenbar nun doch ein anderes. Der Fehler tritt nämlich auch dann auf, wenn die App zum ersten mal installiert wird - also nicht bei einem Update.
      Jetzt bin ich noch ratloser.

      :wacko:

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von klawitter ()