use*_*901 11 macos core-data ios icloud
我有一个OSX和iOS的应用程序,都使用iCloud在它们之间共享核心数据.当我在iPhone上进行更改时,我可以在OSX应用程序中看到它们,并NSPersistentStoreDidImportUbiquitousContentChangesNotification在两个应用程序中调用它们,因此iOS - > Mac运行良好.但是当我在Mac应用程序中进行一些更改时,我无法在iPhone中看到它们.iPhone永远不会打电话给NSPersistentStoreDidImportUbiquitousContentChangesNotification.我能改变Mac的唯一方法是在iPhone上做一些改变.然后我可以看到所有的变化.
两个项目中的iCloud集成是一样的.核心数据数据模型是相同的.权利也是一样的.
我的所有代码都基于这个库:http://ossh.com.au/design-and-technology/software-development/sample-library-style-ios-core-data-app-with-icloud-integration/
为什么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];
}
Run Code Online (Sandbox Code Playgroud)
从单个设备执行此操作似乎都运行良好,但是当我尝试使用多个设备时,我遇到了一些错误.
例:
我有两个设备.第一个没有连接到iCloud,第二个连接到iCloud.在我启用iCloud的第一个设备中,我选择startNewCopy然后在第二个设备中我收到此错误:
CoreData:Ubiquity:Librarian在开始下载时返回严重错误Error Domain = BRCloudDocsErrorDomain Code = 5"操作无法完成.(BRCloudDocsErrorDomain错误5 - 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"];
}];
}
Run Code Online (Sandbox Code Playgroud)
如何检测iCloud内容已被删除并避免上述错误?
在我看来,您可能没有使用适当的接口。
您无需使用任何方法即可将文件移入或移出 iCloud NSPersistentStore。通常,适当的操作也必须包含在调用中NSFileCoordinator。
这是我在 iOS 上所做的。toLocal表示移动到本地(设备)存储或从本地(设备)存储移动:
//
/// Move file between stores (assumed no name clash).
/// Return new URL.
/// Note: cloud file moves are asynchronous.
///
- (NSURL *)moveStoreFile:(NSURL *)url toRootURL:(NSURL *)rootURL toLocal:(BOOL)toLocal
{
NSURL *newURL = rootURL;
if (!toLocal)
newURL = [newURL URLByAppendingPathComponent:@"Documents"];
newURL = [newURL URLByAppendingPathComponent:url.lastPathComponent];
[self backupFile:url isLocal:!toLocal completionHandler:
^(BOOL success) {
MRLOG(@"MOVE %s %@ to %s %@", toLocal? "icloud" : "local", [url lastPathComponent],
toLocal? "local" : "icloud", [newURL lastPathComponent]);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
^{
NSError *error;
// setUbiquitous does file coordination
BOOL msuccess = [[NSFileManager defaultManager]
setUbiquitous:!toLocal itemAtURL:url destinationURL:newURL error:&error];
dispatch_async(dispatch_get_main_queue(),
^{
if (!msuccess)
MRLOG(@"move failed: %@", error);
[self.delegate moveStoreFileCompletedWithStatus:success error:error];
});
});
}];
return newURL;
}
Run Code Online (Sandbox Code Playgroud)
删除需要明确的文件协调:
///
/// Purge backup file (really delete it).
/// Note: cloud deletes are asynchronous.
///
- (void)purgeFile:(NSURL *)url isLocal:(BOOL)isLocal
{
MRLOG(@"PURGE %s %@", isLocal? "local" : "icloud", [url lastPathComponent]);
if (isLocal)
[self removeFile:url];
else
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
^{
NSError *coordinationError;
NSFileCoordinator *coordinator = [[NSFileCoordinator alloc] initWithFilePresenter:nil];
[coordinator coordinateWritingItemAtURL:url options:NSFileCoordinatorWritingForDeleting
error:&coordinationError
byAccessor:
^(NSURL* writingURL)
{
[self removeFile:writingURL];
}];
if (coordinationError) {
MRLOG(@"coordination error: %@", coordinationError);
[(SSApplication *)[SSApplication sharedApplication] fileErrorAlert:coordinationError];
}
});
}
Run Code Online (Sandbox Code Playgroud)
要检测文件的更改,您需要使用NSMetadataQuery并添加观察者NSMetadataQueryDidUpdateNotification。
| 归档时间: |
|
| 查看次数: |
923 次 |
| 最近记录: |