正在将iCloud存储迁移到本地



迁移在模拟器上运行良好。然而,在设备上,我没有看到错误消息,但迁移的存储区是空的。

NSDictionary *iCloudOptions = @{
NSPersistentStoreUbiquitousContentNameKey : @"iCloudNimbleStore",
NSPersistentStoreUbiquitousContentURLKey : @"transactions_logs",
NSMigratePersistentStoresAutomaticallyOption : @YES,
NSInferMappingModelAutomaticallyOption : @YES
};
NSDictionary *localOptions = @{NSMigratePersistentStoresAutomaticallyOption : @YES,
NSInferMappingModelAutomaticallyOption : @YES
};
if (![[NSFileManager defaultManager]fileExistsAtPath:self.storeURL.path]) {
@synchronized(@"Migration")
{
// thread-safe code
if ([[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil]) {
NSLog(@"iCloud");
[self migrateStoreFromURL:[self nb_URLToStoreWithFilename:[self nb_appName]]options:iCloudOptions];
}else{
[self migrateStoreFromURL:[self nb_URLToStoreWithFilename:[NSString stringWithFormat:@"%@.sqlite", [self nb_appName]]] options:localOptions];
//
[self migrateStoreFromURL:[self nb_URLToOldStoreWithFilename] options:localOptions];
}
}
}
NSDictionary *options = @{
NSMigratePersistentStoresAutomaticallyOption:@YES
,NSInferMappingModelAutomaticallyOption:@YES
};
NSError *error = nil;
[_coordinator lock];
_store = [_coordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:[self storeURL] options:options error:&error];
[_coordinator unlock];
if (!_store) {
UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"Loading Fail" message:[NSString stringWithFormat:@"Failed to add store. Error: %@", error] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil];
[alert show];
NSLog(@"Failed to add store. Error: %@", error);abort();
} else {
UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"Loading Success" message:[NSString stringWithFormat:@"Successfully added store: %@", _store] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil];
[alert show];
NSLog(@"Successfully added store: %@", _store);
if (_store && !error) {
// Encrypt the password database
NSError *encrError;
NSDictionary *fileAttributes = [NSDictionary dictionaryWithObject:NSFileProtectionComplete forKey:NSFileProtectionKey];
if (![[NSFileManager defaultManager] setAttributes:fileAttributes ofItemAtPath:self.storeURL.path error:&encrError]){
NSLog(@"Unresolved error with password store encryption %@, %@", encrError, [encrError userInfo]); 
abort();
}else {NSLog(@"Encrypted");}
}
}

以下是迁移过程:

- (void)migrateStoreFromURL:(NSURL *)oldStoreURL options:(NSDictionary *)oldOptions{
if (debug==1) {
TFLog(@"Running %@ '%@'", self.class, NSStringFromSelector(_cmd));
}
if (_store)
{
NSLog(@"NOT NEEDED");
return;
}
UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"Migration" message:[NSString stringWithFormat:@"Found old store at %@",oldStoreURL.path] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil];
[alert show];
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath:self.storeURL.path]) {
NSDictionary *options =
@{
NSMigratePersistentStoresAutomaticallyOption:@YES
,NSInferMappingModelAutomaticallyOption:@YES
};
NSError *error = nil;
[_coordinator lock];
NSPersistentStore *srcPS = [_coordinator addPersistentStoreWithType:NSSQLiteStoreType
            configuration:nil
                      URL:oldStoreURL
                  options:oldOptions
                    error:&error];
_store = [_coordinator migratePersistentStore:srcPS
       toURL:self.storeURL
     options:options
    withType:NSSQLiteStoreType
       error:&error];
[_coordinator unlock];
if (_store && !error) {
UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"Migration Success" message:[NSString stringWithFormat:@"Old store successfully migrated from %@",oldStoreURL.path] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil];
[alert show];
// Encrypt the password database
NSError *encrError;
NSDictionary *fileAttributes = [NSDictionary dictionaryWithObject:NSFileProtectionComplete forKey:NSFileProtectionKey];
if (![[NSFileManager defaultManager] setAttributes:fileAttributes ofItemAtPath:self.storeURL.path error:&encrError]){
UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"Encryption Error" message:[NSString stringWithFormat:@"Unresolved error with password store encryption %@, %@", encrError, [encrError userInfo]] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil];
[alert show];
}
}else{
UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"Migration Error" message:error.localizedDescription delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil];
[alert show];
}
}

更新:我检查了新迁移的存储的大小,结果是0。最奇怪的是_store && !error是真的。我还尝试将NSPersistentStoreRemoveUbiquitousMetadataOption: @YES添加到迁移选项中,但它没有改变任何内容。

上升。2我认为在设备上,iCloud商店的url在加载之前为零。我需要一些变通方法来等待它完成。

我不能100%确定我是否理解您试图对迁移做什么。通过迁移在空存储中播种数据是很常见的,但看起来你正试图将数据从iCloud迁移到本地存储中。是这样吗?你不应该那样做。iCloud应自动将其他设备的数据添加到您的存储中。

这条线看起来也不对:

NSPersistentStoreUbiquitousContentURLKey : @"transactions_logs",

我认为你想在那里使用一个指向iCloud容器内事务日志目录的URL。例如

NSURL *containerURL = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];
NSURL *url = [containerURL URLByAppendingPathComponent:@"transactions_logs"];

使用iCloud时,重要的是要意识到数据不会瞬间传输。它可能需要一段时间才能到达,而且你的应用程序真的无法确定是否有数据。您可以使用元数据查询来监控元数据,但即使是元数据查询,也往往是在其他设备上的数据生成后的一段时间内到达的。

因此,简单地在泛在容器中查找数据并没有多大帮助,因为可能有数据可用,也可能没有数据可用。你只是不知道,你必须考虑到这一假设来制定你的方法,这样它才能处理任何延迟。

使iCloud同步与核心数据协同工作所需的迁移既混乱又不必要。使用一个自动完成这些工作的框架,比如核心数据集成,你可能更有可能让事情顺利进行。(披露:我是Ensembles的开发者。)

最新更新