如何控制 iCloud 何时同步我的核心数据?
Posted
技术标签:
【中文标题】如何控制 iCloud 何时同步我的核心数据?【英文标题】:How can I control when iCloud syncs my core data? 【发布时间】:2012-10-23 02:40:28 【问题描述】:我有以下代码可以将我的核心数据与 iCloud 同步。但是,我只希望它在我说的时候同步。例如,仅在使用 wifi 时同步。我能做到吗?这是我的代码:
- (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;
managedObjectContext.mergePolicy = [[NSMergePolicy alloc]
initWithMergeType:NSMergeByPropertyObjectTrumpMergePolicyType];
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];
];
- (NSManagedObjectModel *)managedObjectModel
if (managedObjectModel != nil)
return managedObjectModel;
NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"EntryDatabase" ofType:@"momd"];
NSURL *modelURL = [NSURL fileURLWithPath:modelPath];
managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
return managedObjectModel;
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
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 = @"iCloud ID is here, i removed it from stack overflow";
// ** Note: if you adapt this code for your own use, you should change this variable:
NSString *dataFileName = @"CoreDataStore.sqlite";
// ** Note: For basic usage you shouldn't need to change anything else
NSString *iCloudDataDirectoryName = @"Data.nosync";
NSString *iCloudLogsDirectoryName = @"Logs";
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *storePath = [[self applicationDocumentsDirectory] stringByAppendingPathComponent:dataFileName];
NSURL *localStore = [NSURL fileURLWithPath:storePath];
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];
);
);
return persistentStoreCoordinator;
【问题讨论】:
Ensembles (ensembles.io) 是我为同步核心数据而开发的框架。它使您可以控制何时同步,并且还会自动迁移和合并现有数据。 【参考方案1】:据我所知,这不可能发生。无论如何都不是以任何简单有效的方式。
http://developer.apple.com/library/mac/#documentation/General/Conceptual/iCloudDesignGuide/Chapters/iCloudFundametals.html
问题是iCloud的操作不是透明的。因此,ios 决定何时进行同步以及多久进行一次同步。在上面的文档中,Apple 说“最佳做法”是专门使用沙盒或专门使用 iCloud,但不要在它们之间复制您的数据。
也就是说,Apple 提到了在 iCloud 不可用时进行操作。这似乎符合您建议的情况。从根本上说,您需要正常设置它,确保您拥有所需的数据,然后停用 iCloud 并将您的数据移动到沙箱以进行处理。当您要同步时,只需将数据复制回来即可。
要处理 iCloud 可用性的变化,请实现一个在接收到 NSUbiquityIdentityDidChangeNotification 通知时调用的方法。您的方法需要执行以下工作:
调用 ubiquityIdentityToken 方法并存储其返回值。 将新值与之前的值进行比较,以了解用户是退出其帐户还是登录到其他帐户。 如果以前使用的帐户现在不可用,请根据需要在本地保存当前状态,清空与 iCloud 相关的数据缓存,并刷新所有与 iCloud 相关的用户界面元素。 如果您希望允许用户在 iCloud 不可用的情况下继续创建内容,请将这些内容存储在您应用的沙盒容器中。当帐户再次可用时,将新内容移至 iCloud。通常最好在不通知用户或要求用户进行任何交互的情况下执行此操作。
这似乎符合您的要求。不过,我自己也才刚到这个阶段,所以我不能进一步评论。
【讨论】:
以上是关于如何控制 iCloud 何时同步我的核心数据?的主要内容,如果未能解决你的问题,请参考以下文章