2011-10-03 162 views
3

我得到在Xcode的组织者,我怀疑是关系到核心数据迁移是需要很长时间才能完成此错误消息(以及随后的崩溃):的iOS核心数据迁移超时

09年10月4日: 51:14未知SpringBoard [30]:appName无法及时启动

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

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

如果不需要迁移,通过在构建过程中提供正确的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:自withObject:无] - >因为迁移仍在进行中,因此表视图无法访问未准备好的托管对象上下文。
  • [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]; 
} 

回答

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(在上面的代码中,您可以直接从-application:didFinishLaunchingWithOptions:调用-persistentStoreLoaded)。

+0

谢谢,这有帮助。我实现了类似于你的第一个建议的东西,只是我通过将Core Data方法放入进度控制器并通过按钮触发迁移来测试这个想法(我将自动执行此操作,但希望首先进行完整性测试)。 – futureshocked

+0

它发生在后台线程中吗?如果没有,它可能会工作,但仍然失败,如果用户背景你的应用程序通过迁移的一半。 –