【发布时间】:2015-11-26 15:30:09
【问题描述】:
我有一个适用于 OSX 和 iOS 的应用程序,并且都使用 iCloud 在它们之间共享核心数据。当我在 iPhone 中进行更改时,我可以在 OSX 应用程序中看到它们,并且在两个应用程序中都调用了 NSPersistentStoreDidImportUbiquitousContentChangesNotification,因此 iOS -> Mac 运行良好。但是当我在 Mac 应用程序上进行一些更改时,我无法在 iPhone 中看到它们。 iPhone 从不调用NSPersistentStoreDidImportUbiquitousContentChangesNotification。我可以获得 Mac 更改的唯一方法是在 iPhone 上进行一些更改。然后我可以看到所有的变化。
两个项目中的 iCloud 集成是相同的。核心数据数据模型是相同的。权利也是一样的。
为什么在我对 iPhone 进行一些更改之前,iPhone 没有获得 Mac 更改?有什么想法吗?
另一个问题
在我的应用程序中,当用户启用 iCloud 时,我会检查是否已经是 iCloud 中的文件。如果文件存在,用户可以选择从 iCloud 文件恢复核心数据或从本地存储开始新副本。 要开始一个新副本,我使用以下代码:
- (void)startNewCopy
{
[self removeICloudStore];
[self moveStoreToIcloud];
}
- (void)removeICloudStore
{
BOOL result;
NSError *error;
// Now delete the iCloud content and file
result = [NSPersistentStoreCoordinator removeUbiquitousContentAndPersistentStoreAtURL:[self icloudStoreURL]
options:[self icloudStoreOptions]
error:&error];
if (!result)
{
NSLog(@"Error removing store");
}
else
{
NSLog(@"Core Data store removed.");
// Now delete the local file
[self deleteLocalCopyOfiCloudStore];
}
}
- (void)deleteLocalCopyOfiCloudStore {
// We need to get the URL to the store
NSError *error = nil;
[[NSFileManager defaultManager] removeItemAtURL:[self localUbiquitySupportURL] error:&error];
}
- (void)moveStoreToIcloud
{
// Open the store
NSPersistentStore *sourceStore = [[_persistentStoreCoordinator persistentStores] firstObject];
if (!sourceStore)
{
NSLog(@" failed to add old store");
}
else
{
NSLog(@" Successfully added store to migrate");
NSError *error;
id migrationSuccess = [_persistentStoreCoordinator migratePersistentStore:sourceStore toURL:[self icloudStoreURL] options:[self icloudStoreOptions] withType:NSSQLiteStoreType error:&error];
if (migrationSuccess)
{
NSLog(@"Store migrated to iCloud");
_persistentStoreCoordinator = nil;
_managedObjectContext = nil;
// Now delete the local file
[self deleteLocalStore];
}
else
{
NSLog(@"Failed to migrate store: %@, %@", error, error.userInfo);
}
}
}
- (void)deleteLocalStore
{
NSError *error = nil;
[[NSFileManager defaultManager] removeItemAtURL:[self localStoreURL] error:&error];
}
在单个设备上执行此操作似乎一切正常,但是当我在多个设备上尝试此操作时,我遇到了一些错误。
例子:
我有两个设备。第一个未连接到 iCloud,第二个连接到 iCloud。
在我启用 iCloud 的第一台设备中,我选择 startNewCopy,然后在第二台设备中出现此错误:
CoreData: Ubiquity: Librarian 在开始下载时返回了一个严重错误 Error Domain=BRCloudDocsErrorDomain Code=5 "The operation could not be completed. (BRCloudDocsErrorDomain error 5 - No document at URL)"
NSPersistentStoreCoordinatorStoresDidChangeNotification 在错误之前从未被调用。
这是我的通知代码:
- (void)processStoresDidChange:(NSNotification *)notification
{
NSLog(@"processStoresDidChange");
// Post notification to trigger UI updates
// Check type of transition
NSNumber *type = [notification.userInfo objectForKey:NSPersistentStoreUbiquitousTransitionTypeKey];
//NSLog(@" userInfo is %@", notification.userInfo);
//NSLog(@" transition type is %@", type);
if (type.intValue == NSPersistentStoreUbiquitousTransitionTypeInitialImportCompleted) {
NSLog(@" transition type is NSPersistentStoreUbiquitousTransitionTypeInitialImportCompleted");
} else if (type.intValue == NSPersistentStoreUbiquitousTransitionTypeAccountAdded) {
NSLog(@" transition type is NSPersistentStoreUbiquitousTransitionTypeAccountAdded");
} else if (type.intValue == NSPersistentStoreUbiquitousTransitionTypeAccountRemoved) {
NSLog(@" transition type is NSPersistentStoreUbiquitousTransitionTypeAccountRemoved");
} else if (type.intValue == NSPersistentStoreUbiquitousTransitionTypeContentRemoved) {
NSLog(@" transition type is NSPersistentStoreUbiquitousTransitionTypeContentRemoved");
}
[[NSOperationQueue mainQueue] addOperationWithBlock:^ {
if (type.intValue == NSPersistentStoreUbiquitousTransitionTypeContentRemoved) {
[self deleteLocalStore];
_persistentStoreCoordinator = nil;
_managedObjectContext = nil;
NSLog(@" iCloud store was removed! Wait for empty store");
}
// Refresh user Interface
[[NSNotificationCenter defaultCenter] postNotificationName:@"notiIcloud" object:@"storeChanged"];
}];
}
如何检测到 iCloud 内容已被删除并避免出现上述错误?
【问题讨论】:
-
这并不能真正回答你的问题,但我很久以前就放弃了使用支持 iCloud 的 Core Data。然后我编写了自己的同步,但它有点受限。然后我找到了 Ensembles (ensembles.io) 并且一直在使用它。这对我来说太棒了。有一个免费的开源版本。
-
谢谢回答,但我更喜欢使用苹果的标准 iCloud 支持。
-
我写了你正在使用的代码,你测试的是什么版本的 iOS、OSX 和 XCode?span>
-
ios 8,osx 10.10,xcode 6.3。 iphone之间的同步效果很好。我需要确切地知道在 mac 和 iphone 之间同步核心数据的要求是什么。也许我忘记了什么:S
-
您是否尝试过编译和运行示例应用程序,除了容器 ID 之外没有任何更改?它们应该开箱即用,尽管请记住该代码中未涵盖一些边缘情况。还要检查 Mac 上的 iCloud 文件夹以查看是否所有事务文件都在那里,使用终端会话并输入类似
ls -R "Library/Mobile Documents/iCloud~au~com~ossh~iWallet2"的内容
标签: ios macos core-data icloud