2012-10-12 81 views
1

当用户升级或重新安装较新版本的iOS应用程序时,是否有任何委托方法会被调用?ios应用程序升级代表

我使用核心数据从服务器缓存一些信息。当任何实体的模式发生变化时,我需要从模拟器手动删除SQLite数据库,否则应用程序将在启动时崩溃,并出现错误“用于打开商店的模型与用于创建商店的模型不兼容“。如果有任何应用程序升级的委托方法,则可以自动执行删除操作。

回答

4
+0

感谢您的链接。也许这不值得版本控制的复杂性,因为它只是一个缓存,并且我总是可以从服务器中恢复其中的信息。在AppDelegate的' - (NSPersistentStoreCoordinator *)persistentStoreCoordinator'的默认实现中的注释给了我使用的解决方案:'[[NSFileManager defaultManager] removeItemAtURL:storeURL error:nil];'当它失败时[_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType配置:无URL:storeURL选项:无错误:错误]' –

2

丹尼尔·史密斯的答案是正确的,但我只想补充我的应用程序如何确定其被更新。我看在默认情况下保留一个'当前版本'字符串。当应用程序启动时,我把它比作当前版本:

  • 默认已经没有字符串 - 这是程序的第一个运行
  • 默认版本是不同的 - 用户更新应用
  • 默认是相同的 - 用户刚刚重新启动应用程序

有时很高兴知道上述。确保在设置标签后立即保存默认值并进行所需的版本控制,因此崩溃不会再次执行。

编辑:如果他模型的变化如何不崩溃。我现在使用它,保留旧的存储库,并调整模型,每调整一次,它就删除旧的(如果它无法打开它)并创建一个新的。这是模仿苹果的代码,但不知道我做了什么改变。在任何情况下,如果模型更改,您都不会崩溃。

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator 
{ 
    //LTLog(@"_persistentStoreCoordinator = %@", _persistentStoreCoordinator); 
    if (_persistentStoreCoordinator) 
    { 
     return _persistentStoreCoordinator; 
    } 
    NSFileManager *manager = [NSFileManager defaultManager]; 
    NSString *path = [[appDelegate applicationAppSupportDirectory] stringByAppendingPathComponent:[_dbName stringByAppendingPathExtension:@"SQLite"]]; 
    storeURL = [NSURL fileURLWithPath:path]; 

    BOOL fileExists = [manager fileExistsAtPath:path]; 
    if(!fileExists) { 
     _didCreateNewRepository = YES; 
    } 
    if(_createNewRepository) { 
     [manager removeItemAtURL:storeURL error:nil]; 
     if(fileExists) _didDestroyOldRepository = YES; 
     _didCreateNewRepository = YES; 
    } 

    while(YES) { 
     __autoreleasing NSError *error = nil; 
     _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]]; 
     if ([_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) { 

      break; 
     } else { 
      _persistentStoreCoordinator = nil; 
      [manager removeItemAtURL:storeURL error:&error]; 
      if(fileExists) { 
       _didDestroyOldRepository = YES; // caller didn't want a new one but got a new one anyway (old one corrupt???) 
       _didCreateNewRepository = YES; 
      } 
#ifndef NDEBUG 
      LTLog(@"CORE DATA failed to open store %@: error=%@", _dbName, error); 
#endif 
      /* 
      Replace this implementation with code to handle the error appropriately. 

      abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. If it is not possible to recover from the error, display an alert panel that instructs the user to quit the application by pressing the Home button. 

      Typical reasons for an error here include: 
      * The persistent store is not accessible 
      * The schema for the persistent store is incompatible with current managed object model 
      Check the error message to determine what the actual problem was. 
      */ 
      //LTLog(@"Unresolved error %@, %@", error, [error userInfo]); 
      //abort(); 
     }  
    } 
    return _persistentStoreCoordinator; 
} 
+0

好主意。我将保存它以供将来使用。 –