Ios iCloud与Coredata同步
这是我的代码:Ios iCloud与Coredata同步,ios,core-data,icloud,Ios,Core Data,Icloud,这是我的代码: 这是具有Coredata同步配置代码的iCloud: #pragma mark - Core Data stack @synthesize managedObjectContext = _managedObjectContext; @synthesize managedObjectModel = _managedObjectModel; @synthesize persistentStoreCoordinator = _persi
这是具有Coredata同步配置代码的iCloud:
#pragma mark - Core Data stack
@synthesize managedObjectContext = _managedObjectContext;
@synthesize managedObjectModel = _managedObjectModel;
@synthesize persistentStoreCoordinator = _persistentStoreCoordinator;
- (NSURL *)applicationDocumentsDirectory {
// The directory the application uses to store the Core Data store file. This code uses a directory named "com.wanglichen.iPassword" in the application's documents directory.
return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}
- (NSManagedObjectModel *)managedObjectModel {
// The managed object model for the application. It is a fatal error for the application not to be able to find and load its model.
if (_managedObjectModel != nil) {
return _managedObjectModel;
}
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"iPassword" withExtension:@"momd"];
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
return _managedObjectModel;
}
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
// create a new persistent store of the appropriate type
NSError *error = nil;
NSURL *storeURL = [self applicationDocumentsDirectory];
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:self.managedObjectModel];
// ** Note: if you adapt this code for your own use, you MUST change this variable.
// is the full App ID (including the Team Prefix). You will need to change this to match the Team Prefix found in your own iOS Provisioning Portal.
NSString *iCloudEnabledAppID = [[NSBundle mainBundle] infoDictionary][@"CFBundleIdentifier"];
// the name of the SQLite database store file.
NSString *dataFileName = @"iPassword.sqlite";
// ** Note: For basic usage you shouldn't need to change anything else
// dataDirectory is the name of the directory the database will be stored in. It should always end with .nosync
// iCloudData = iCloudRootPath + dataDirectory
NSString *iCloudDataDirectoryName = @"Data.nosync";
// logsDirectory is the name of the directory the database change logs will be stored in.
NSString *iCloudLogsDirectoryName = @"Logs";
NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *localStore = [storeURL URLByAppendingPathComponent:dataFileName];
// iCloudRootPath is the URL to your apps iCloud root path.
NSURL *iCloudRootPath = [fileManager URLForUbiquityContainerIdentifier:nil];
if (iCloudRootPath) // If iCloud is working, save it to iCloud container.
{
NSLog(@"iCloud is working.");
// Place core data sqlite file in iCloudRootPath/Data.nosync/ (The subdirectory should be ended with .nosync)
// Place the log file in iCloudRootPath/Logs (All changed in iCloud will be download to log file firstly.)
NSURL *iCloudLogsPath = [iCloudRootPath URLByAppendingPathComponent:iCloudLogsDirectoryName];
// NSLog(@"iCloudEnabledAppID = %@",iCloudEnabledAppID);
// NSLog(@"dataFileName = %@", dataFileName);
// NSLog(@"iCloudDataDirectoryName = %@", iCloudDataDirectoryName);
// NSLog(@"iCloudLogsDirectoryName = %@", iCloudLogsDirectoryName);
// NSLog(@"iCloud = %@", iCloudRootPath);
// NSLog(@"iCloudLogsPath = %@", iCloudLogsPath);
NSURL *iCloudDataURL = [iCloudRootPath URLByAppendingPathComponent:iCloudDataDirectoryName];
if ([fileManager fileExistsAtPath:[iCloudDataURL path]] == NO)
{
NSError *fileSystemError;
[fileManager createDirectoryAtPath:[iCloudDataURL path]
withIntermediateDirectories:YES
attributes:nil
error:&fileSystemError];
if(fileSystemError != nil)
{
NSLog(@"Error creating database directory %@", fileSystemError);
}
}
iCloudDataURL = [iCloudDataURL URLByAppendingPathComponent:dataFileName];
// NSLog(@"iCloudDataPath = %@", iCloudDataURL);
NSMutableDictionary *options = [NSMutableDictionary dictionary];
[options setObject:@(YES) forKey:NSMigratePersistentStoresAutomaticallyOption];
[options setObject:@(YES) forKey:NSInferMappingModelAutomaticallyOption];
[options setObject:iCloudEnabledAppID forKey:NSPersistentStoreUbiquitousContentNameKey];
[options setObject:iCloudLogsPath forKey:NSPersistentStoreUbiquitousContentURLKey];
[_persistentStoreCoordinator lock];
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:iCloudDataURL
options:options
error:nil])
{
NSDictionary *ui = [error userInfo];
for(NSString *err in [ui keyEnumerator]) {
NSLog(@"err:%@",[ui objectForKey:err]);
}
abort();
}
[_persistentStoreCoordinator unlock];
}
else // If iCloud is not working, save it to local.
{
NSLog(@"iCloud is NOT working - using a local store");
NSMutableDictionary *options = [NSMutableDictionary dictionary];
[options setObject:@(YES) forKey:NSMigratePersistentStoresAutomaticallyOption];
[options setObject:@(YES) forKey:NSInferMappingModelAutomaticallyOption];
[options setObject:@(YES) forKey:NSMigratePersistentStoresAutomaticallyOption];
[options setObject:@(YES) forKey:NSInferMappingModelAutomaticallyOption];
[_persistentStoreCoordinator lock];
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:localStore
options:options
error:nil])
{
NSDictionary *ui = [error userInfo];
for(NSString *err in [ui keyEnumerator]) {
NSLog(@"err:%@",[ui objectForKey:err]);
}
abort();
}
[_persistentStoreCoordinator unlock];
}
return _persistentStoreCoordinator;
}
- (NSManagedObjectContext *)managedObjectContext {
// Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.)
if (_managedObjectContext != nil) {
return _managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (!coordinator) {
return nil;
}
_managedObjectContext = [[NSManagedObjectContext alloc] init];
[_managedObjectContext setPersistentStoreCoordinator:coordinator];
// Register NSPersistentStoreDidImportUbiquitousContentChangesNotification, so that
// coreDataChangedIniCloud will be called if core data in iCloud is changed.
[[NSNotificationCenter defaultCenter]addObserver:self
selector:@selector(coreDataChangedIniCloud:)
name:NSPersistentStoreDidImportUbiquitousContentChangesNotification
object:self.persistentStoreCoordinator];
return _managedObjectContext;
}
- (void)coreDataChangedIniCloud:(NSNotification *)notification
{
NSLog(@"Merging in changes from iCloud...");
[self.managedObjectContext performBlock:^{
[self.managedObjectContext mergeChangesFromContextDidSaveNotification:notification];
NSLog(@"new data from iCloud: %@", notification.object);
[[NSNotificationCenter defaultCenter] postNotificationName:@"MergingInChangesFromICloud" object:notification.object userInfo:[notification userInfo]];
}];
}
#pragma mark - Core Data Saving support
- (void)saveContext {
NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
if (managedObjectContext != nil) {
NSError *error = nil;
if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {
// 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.
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
}
}
以下是我遇到的问题:
碰撞痕迹
当iCloud中的数据发生变化时,我调用以下方法:
- (void)coreDataChangedIniCloud:(NSNotification *)notification
{
NSLog(@"Merging in changes from iCloud...");
[self.managedObjectContext performBlock:^{
[self.managedObjectContext mergeChangesFromContextDidSaveNotification:notification];
NSLog(@"new data from iCloud: %@", notification.object);
[[NSNotificationCenter defaultCenter] postNotificationName:@"MergingInChangesFromICloud" object:notification.object userInfo:[notification userInfo]];
}];
}
这是导致坠机的原因:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Can only use -performBlock: on an NSManagedObjectContext that was created with a queue.
试试这个
_managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
- (void)coreDataChangedIniCloud:(NSNotification *)notification
NSManagedObjectContext *moc = self.managedObjectContext;
[moc performBlockAndWait:^{
[moc mergeChangesFromContextDidSaveNotification:notification];
}];
dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:@"MergingInChangesFromICloud" object:notification.object userInfo:[notification userInfo]];
});
}
试试这个
_managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
- (void)coreDataChangedIniCloud:(NSNotification *)notification
NSManagedObjectContext *moc = self.managedObjectContext;
[moc performBlockAndWait:^{
[moc mergeChangesFromContextDidSaveNotification:notification];
}];
dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:@"MergingInChangesFromICloud" object:notification.object userInfo:[notification userInfo]];
});
}
试试这个
_managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
- (void)coreDataChangedIniCloud:(NSNotification *)notification
NSManagedObjectContext *moc = self.managedObjectContext;
[moc performBlockAndWait:^{
[moc mergeChangesFromContextDidSaveNotification:notification];
}];
dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:@"MergingInChangesFromICloud" object:notification.object userInfo:[notification userInfo]];
});
}
试试这个
_managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
- (void)coreDataChangedIniCloud:(NSNotification *)notification
NSManagedObjectContext *moc = self.managedObjectContext;
[moc performBlockAndWait:^{
[moc mergeChangesFromContextDidSaveNotification:notification];
}];
dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:@"MergingInChangesFromICloud" object:notification.object userInfo:[notification userInfo]];
});
}
performBlock(和performBlockAndWait)只能用于使用NSPrivateQueueConcurrencyType或NSMainQueueConcurrencyType初始化的NSManagedObjectContext。默认情况下,初始化NSManagedObjectContext以使用不支持performBlock或performBlockAndWait的NSConfiginementConcurrencyType
您应该更改此行:
_managedObjectContext = [[NSManagedObjectContext alloc] init];
致:
_managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
或
performBlock(和performBlockAndWait)只能用于使用NSPrivateQueueConcurrencyType或NSMainQueueConcurrencyType初始化的NSManagedObjectContext。默认情况下,初始化NSManagedObjectContext以使用不支持performBlock或performBlockAndWait的NSConfiginementConcurrencyType
您应该更改此行:
_managedObjectContext = [[NSManagedObjectContext alloc] init];
致:
_managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
或
performBlock(和performBlockAndWait)只能用于使用NSPrivateQueueConcurrencyType或NSMainQueueConcurrencyType初始化的NSManagedObjectContext。默认情况下,初始化NSManagedObjectContext以使用不支持performBlock或performBlockAndWait的NSConfiginementConcurrencyType
您应该更改此行:
_managedObjectContext = [[NSManagedObjectContext alloc] init];
致:
_managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
或
performBlock(和performBlockAndWait)只能用于使用NSPrivateQueueConcurrencyType或NSMainQueueConcurrencyType初始化的NSManagedObjectContext。默认情况下,初始化NSManagedObjectContext以使用不支持performBlock或performBlockAndWait的NSConfiginementConcurrencyType
您应该更改此行:
_managedObjectContext = [[NSManagedObjectContext alloc] init];
致:
_managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
或
您是否会发布异常(在代码标记中)?谢谢。由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“只能在使用队列创建的NSManagedObjectContext上使用-performBlock:。错误标记-(void)CoreDataChangedInCloud:(NSNotification*)通知您是否会发布异常(在代码标记中)?谢谢。由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“只能在使用队列创建的NSManagedObjectContext上使用-performBlock:。错误标记-(void)CoreDataChangedInCloud:(NSNotification*)通知您是否会发布异常(在代码标记中)?谢谢。由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“只能在使用队列创建的NSManagedObjectContext上使用-performBlock:。错误标记-(void)CoreDataChangedInCloud:(NSNotification*)通知您是否会发布异常(在代码标记中)?谢谢。由于未捕获异常“NSInvalidArgumentException”而终止应用程序,原因:“只能在使用队列创建的NSManagedObjectContext上使用-performBlock:。错误标记-(void)CoreDataChangedInicCloud:(NSNotification*)Notification还报告了相同的错误***由于未捕获的异常“NSInvalidArgumentException”终止应用程序,原因:“只能在使用队列创建的NSManagedObjectContext上使用-performBlockAndWait:”。请尝试以下示例代码。谢谢你的帮助!还报告了相同的错误***由于未捕获的异常“NSInvalidArgumentException”终止应用程序,原因是:“只能在使用队列创建的NSManagedObjectContext上使用-performBlockAndWait:”。请尝试以下示例代码。谢谢你的帮助!还报告了相同的错误***由于未捕获的异常“NSInvalidArgumentException”终止应用程序,原因是:“只能在使用队列创建的NSManagedObjectContext上使用-performBlockAndWait:”。请尝试以下示例代码。谢谢你的帮助!还报告了相同的错误***由于未捕获的异常“NSInvalidArgumentException”终止应用程序,原因是:“只能在使用队列创建的NSManagedObjectContext上使用-performBlockAndWait:”。请尝试以下示例代码。谢谢你的帮助!非常感谢!Bug已经修复。非常感谢!Bug已经修复。非常感谢!Bug已经修复。非常感谢!Bug已经修复。非常感谢!Bug已经修复。