的iOS核心数据迁移超时
我得到在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];
}
我认为你需要推迟显示导航控制器,直到迁移完成,也就是说,你可能需要显示“进度控制器”。
最简单的方法可能是在启动时显示进度控制:
- (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
)。
谢谢,这有帮助。我实现了类似于你的第一个建议的东西,只是我通过将Core Data方法放入进度控制器并通过按钮触发迁移来测试这个想法(我将自动执行此操作,但希望首先进行完整性测试)。 – futureshocked
它发生在后台线程中吗?如果没有,它可能会工作,但仍然失败,如果用户背景你的应用程序通过迁移的一半。 –