启用iCloud时首次启动iOS应用程序将冻结

我在iOS应用程序中启用了iCloud,当我按下应用程序中的任何视图时,应用程序第一次启动时,应用程序冻结约5秒钟。 我遵循这个教程,在我的应用程序中启用iCloud,并使用核心数据同步数据。 在添加iCloud同步之前,我没有这个问题。 这只发生在第一次启动,而不是其他应用程序的启动。 iCloud同步确实发生。 问题是应用程序冻结。

这是pipe理我的应用程序委托中的同步的代码。

- (NSURL *)applicationDocumentsDirectory { return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]; } - (NSPersistentStoreCoordinator *)persistentStoreCoordinator { /*if (persistentStoreCoordinator == nil) { NSURL *storeURL = [NSURL fileURLWithPath:[self dataStorePath]]; persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:self.managedObjectModel]; NSError *error; if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) { NSLog(@"Error adding persistent store %@, %@", error, [error userInfo]); abort(); } } return persistentStoreCoordinator;*/ [UIApplication sharedApplication].networkActivityIndicatorVisible = YES; if ((persistentStoreCoordinator != nil)) { return persistentStoreCoordinator; } persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]]; NSPersistentStoreCoordinator *psc = persistentStoreCoordinator; // Set up iCloud in another thread: dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ // ** Note: if you adapt this code for your own use, you MUST change this variable: NSString *iCloudEnabledAppID = @"48S27G4A2S.com.maxned.iDownloadBlog"; // ** Note: if you adapt this code for your own use, you should change this variable: NSString *dataFileName = @"DataStore.sqlite"; // ** Note: For basic usage you shouldn't need to change anything else NSString *iCloudDataDirectoryName = @"Data.nosync"; NSString *iCloudLogsDirectoryName = @"Logs"; NSFileManager *fileManager = [NSFileManager defaultManager]; NSURL *localStore = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:dataFileName]; NSURL *iCloud = [fileManager URLForUbiquityContainerIdentifier:nil]; if (iCloud) { //NSLog(@"iCloud is working"); NSURL *iCloudLogsPath = [NSURL fileURLWithPath:[[iCloud path] stringByAppendingPathComponent:iCloudLogsDirectoryName]]; /*NSLog(@"iCloudEnabledAppID = %@",iCloudEnabledAppID); NSLog(@"dataFileName = %@", dataFileName); NSLog(@"iCloudDataDirectoryName = %@", iCloudDataDirectoryName); NSLog(@"iCloudLogsDirectoryName = %@", iCloudLogsDirectoryName); NSLog(@"iCloud = %@", iCloud); NSLog(@"iCloudLogsPath = %@", iCloudLogsPath);*/ if ([fileManager fileExistsAtPath:[[iCloud path] stringByAppendingPathComponent:iCloudDataDirectoryName]] == NO) { NSError *fileSystemError; [fileManager createDirectoryAtPath:[[iCloud path] stringByAppendingPathComponent:iCloudDataDirectoryName] withIntermediateDirectories:YES attributes:nil error:&fileSystemError]; if (fileSystemError != nil) { NSLog(@"Error creating database directory %@", fileSystemError); } } NSString *iCloudData = [[[iCloud path] stringByAppendingPathComponent:iCloudDataDirectoryName] stringByAppendingPathComponent:dataFileName]; //NSLog(@"iCloudData = %@", iCloudData); NSMutableDictionary *options = [NSMutableDictionary dictionary]; [options setObject:[NSNumber numberWithBool:YES] forKey:NSMigratePersistentStoresAutomaticallyOption]; [options setObject:[NSNumber numberWithBool:YES] forKey:NSInferMappingModelAutomaticallyOption]; [options setObject:iCloudEnabledAppID forKey:NSPersistentStoreUbiquitousContentNameKey]; [options setObject:iCloudLogsPath forKey:NSPersistentStoreUbiquitousContentURLKey]; [psc lock]; [psc addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:[NSURL fileURLWithPath:iCloudData] options:options error:nil]; [psc unlock]; } else { NSLog(@"iCloud is NOT working - using a local store"); NSMutableDictionary *options = [NSMutableDictionary dictionary]; [options setObject:[NSNumber numberWithBool:YES] forKey:NSMigratePersistentStoresAutomaticallyOption]; [options setObject:[NSNumber numberWithBool:YES] forKey:NSInferMappingModelAutomaticallyOption]; [psc lock]; [psc addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:localStore options:options error:nil]; [psc unlock]; } dispatch_async(dispatch_get_main_queue(), ^{ [[NSNotificationCenter defaultCenter] postNotificationName:@"SomethingChanged" object:self userInfo:nil]; }); }); [UIApplication sharedApplication].networkActivityIndicatorVisible = NO; return persistentStoreCoordinator; } /*- (NSManagedObjectContext *)managedObjectContext { if (managedObjectContext == nil) { NSPersistentStoreCoordinator *coordinator = self.persistentStoreCoordinator; if (coordinator != nil) { managedObjectContext = [[NSManagedObjectContext alloc] init]; [managedObjectContext setPersistentStoreCoordinator:coordinator]; } } return managedObjectContext; }*/ - (NSManagedObjectContext *)managedObjectContext { if (managedObjectContext != nil) { return managedObjectContext; } NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator]; if (coordinator != nil) { NSManagedObjectContext *moc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType]; [moc performBlockAndWait:^{ [moc setPersistentStoreCoordinator: coordinator]; [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(mergeChangesFrom_iCloud:) name:NSPersistentStoreDidImportUbiquitousContentChangesNotification object:coordinator]; }]; managedObjectContext = moc; } return managedObjectContext; } - (void)mergeChangesFrom_iCloud:(NSNotification *)notification { //NSLog(@"Merging in changes from iCloud..."); NSManagedObjectContext* moc = [self managedObjectContext]; [moc performBlock:^{ [moc mergeChangesFromContextDidSaveNotification:notification]; NSNotification* refreshNotification = [NSNotification notificationWithName:@"SomethingChanged" object:self userInfo:[notification userInfo]]; [[NSNotificationCenter defaultCenter] postNotification:refreshNotification]; }]; } 

为了解决这个问题,我改变了代码把它放在另一个线程中。

 dispatch_queue_t mainQueue = dispatch_get_main_queue(); dispatch_async(mainQueue, ^{ NSFileManager *fileManager = [NSFileManager defaultManager]; NSURL *localStore = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:dataFileName]; NSURL *iCloud = [fileManager URLForUbiquityContainerIdentifier:nil]; if (iCloud) { //NSLog(@"iCloud is working"); NSURL *iCloudLogsPath = [NSURL fileURLWithPath:[[iCloud path] stringByAppendingPathComponent:iCloudLogsDirectoryName]]; /*NSLog(@"iCloudEnabledAppID = %@",iCloudEnabledAppID); NSLog(@"dataFileName = %@", dataFileName); NSLog(@"iCloudDataDirectoryName = %@", iCloudDataDirectoryName); NSLog(@"iCloudLogsDirectoryName = %@", iCloudLogsDirectoryName); NSLog(@"iCloud = %@", iCloud); NSLog(@"iCloudLogsPath = %@", iCloudLogsPath);*/ if ([fileManager fileExistsAtPath:[[iCloud path] stringByAppendingPathComponent:iCloudDataDirectoryName]] == NO) { NSError *fileSystemError; [fileManager createDirectoryAtPath:[[iCloud path] stringByAppendingPathComponent:iCloudDataDirectoryName] withIntermediateDirectories:YES attributes:nil error:&fileSystemError]; if (fileSystemError != nil) { NSLog(@"Error creating database directory %@", fileSystemError); } } NSString *iCloudData = [[[iCloud path] stringByAppendingPathComponent:iCloudDataDirectoryName] stringByAppendingPathComponent:dataFileName]; //NSLog(@"iCloudData = %@", iCloudData); NSMutableDictionary *options = [NSMutableDictionary dictionary]; [options setObject:[NSNumber numberWithBool:YES] forKey:NSMigratePersistentStoresAutomaticallyOption]; [options setObject:[NSNumber numberWithBool:YES] forKey:NSInferMappingModelAutomaticallyOption]; [options setObject:iCloudEnabledAppID forKey:NSPersistentStoreUbiquitousContentNameKey]; [options setObject:iCloudLogsPath forKey:NSPersistentStoreUbiquitousContentURLKey]; [psc lock]; [psc addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:[NSURL fileURLWithPath:iCloudData] options:options error:nil]; [psc unlock]; } else { NSLog(@"iCloud is NOT working - using a local store"); NSMutableDictionary *options = [NSMutableDictionary dictionary]; [options setObject:[NSNumber numberWithBool:YES] forKey:NSMigratePersistentStoresAutomaticallyOption]; [options setObject:[NSNumber numberWithBool:YES] forKey:NSInferMappingModelAutomaticallyOption]; [psc lock]; [psc addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:localStore options:options error:nil]; [psc unlock]; } }); 

如果这个代码在主线程上运行,那可能是你的问题。

从第一次(或任何)启动时调用此代码的位置?

做一些自我search,看起来像这是实际预期的行为。 正如其他人所说,在更改隐私设置时,应用程序被SIGKILL杀死,并在这里: https : //devforums.apple.com/message/715855

这是logging不完善,但按devise工作。 “在任何权限更改上,iOS都会终止你的应用程序,这样你就不会以任何权限为前提来操作,例如让用户给你联系人的权限,然后他们为你的应用程序设置背景,如果你现在没有权限的话,你可以根据自己的想法进行操作,所以iOS只是终止了应用程序。

“但它不会崩溃,只是被迫重启,你会得到一个SIGKILL消息,但没有崩溃日志。