iOS核心数据迁移超时

时间:2011-10-03 23:16:30

标签: ios core-data core-data-migration

我在Xcode组织器中收到此错误消息(以及随后的崩溃),我怀疑它与核心数据迁移有关,需要很长时间才能完成:

  

Oct 4 09:51:14未知的SpringBoard [30]:appName未能及时发布

此迁移可在模拟器中找到,即使我插入人为延迟(例如,使用sleep(100))。

只有当我尝试在iPhone 4或iPod第4代上测试时才会收到此超时错误消息。

如果不需要迁移,通过在构建期间提供正确的sqlite3数据库版本,不会发生崩溃。

以下是代码中发生的事情:

在应用程序委托中:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    

    PropertiesTableViewController *propertiesTableViewController = 
            [[PropertiesTableViewController alloc] initWithManagedObjectContext:self.managedObjectContext];

    UINavigationController *newNavController = 
                        [[UINavigationController alloc] 
                         initWithRootViewController:propertiesTableViewController];


    [propertiesTableViewController release];
    [window addSubview:newNavController.view];


    NSLog(@"UUID: %@", [[UIDevice currentDevice] uniqueIdentifier]);

    [window makeKeyAndVisible];

    return YES;
}


- (NSManagedObjectContext *) managedObjectContext {

    if (managedObjectContext != nil) {
        return managedObjectContext;
    }

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
    if (coordinator != nil) {
        managedObjectContext = [[NSManagedObjectContext alloc] init];
        [managedObjectContext setPersistentStoreCoordinator: coordinator];
    }
    return managedObjectContext;
}`

persistentStoreCoordinator是一个相当长的方法,很高兴在需要时提供它。它迁移两个数据库,每个数据库大约500kBytes。第一个总是成功,但第二个总是失败(在设备上),但两者总是在模拟器中成功。 propertiesTableViewController提供了一个表视图,其中包含从迁移的数据库中获取的数据,因此必须在propertiesTableViewController查看之前进行迁移。

我还尝试使用以下方法尝试从propertiesTableViewController内部(在viewDidLoad方法中)触发迁移:

  • [NSThread detachNewThreadSelector:@selector(getMOC)toTarget:self withObject:nil] - >崩溃,因为表视图无法访问尚未就绪的托管对象上下文,因为迁移仍在进行中。
  • [self performSelectorOnMainThread:@selector(getMOC)withObject:nil waitUntilDone:YES]; - >崩溃时出现相同的超时错误

getMOC方法是:

-(void)getMOC
{
    NSAutoreleasePool *autoreleasePoolProperty = [[NSAutoreleasePool alloc] init];
    NSLog(@"getting appDelegate from PropertiesTableViewController");

    iNspectorAppDelegate *appDelegate = (iNspectorAppDelegate *)[[UIApplication sharedApplication] delegate];
    NSLog(@"getting managedObjectContext from PropertiesTableViewController");    
    self.managedObjectContext = [appDelegate managedObjectContext];
    NSLog(@"got managedObjectContext from PropertiesTableViewController");   
    [autoreleasePoolProperty release];  
    [self performSelectorOnMainThread:@selector(finishedGettingPropertyData) withObject:nil waitUntilDone:NO];
}

1 个答案:

答案 0 :(得分:6)

我认为您需要推迟显示导航控制器,直到迁移完成,即您可能需要显示“进度控制器”。

最简单的方法可能是在启动时显示进度控制器:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
{
  ...
  [window addSubview:progressController.view];
  [window makeKeyAndVisible];
  [self performSelectorInBackground:@selector(loadPersistentStore) withObject:nil];
}

-(void)loadPersistentStore
{
  [self persistentStoreCoordinator];
  [self performSelectorOnMainThread:@selector(persistentStoreLoaded) withObject:nil waitUntilDone:NO];`
}

-(void)persistentStoreLoaded
{
  [progressController.view removeFromSuperview];
  self.progressController = nil;

  // Load the normal VC here
  ...
}

稍微好一点的选择是首先尝试加载关闭NSMigratePersistentStoresAutomaticallyOption的持久存储。如果失败,则显示进度VC并在后台再次尝试;如果成功,则可以直接显示正常的VC(在上面的代码中,您可以直接从-persistentStoreLoaded调用-application:didFinishLaunchingWithOptions:。)