gpt4 book ai didi

ios - 将 iCloud 商店迁移到本地商店并确保数据在每次应用程序启动时都在那里

转载 作者:可可西里 更新时间:2023-11-01 05:53:44 27 4
gpt4 key购买 nike

基于这里的问题:Migrate iCloud data to Local store and stopping iCloud from still responding关于将 iCloud 商店移至本地商店并确保禁用 iCloud 通知,我遇到了下一个场景。

问题

现在,当用户在第一台设备上运行该应用程序时,系统会在开始时询问他们是否要启用 iCloud。如果他们选择是,数据将迁移到 iCloud。如果用户连接第二台设备,系统会在一开始询问他们是否要使用 iCloud,如果他们选择是,来自第一台设备的数据将同步。

如果第二台设备上的用户决定他们不想再使用 iCloud,他们可以在该设备的应用程序中专门导航并关闭 iCloud。这在后端会将他们的数据从 iCloud 存储迁移到本地存储。从用户的角度来看,他们所有的数据都在那里(无论是存储在云端还是本地,此时对用户来说都无关紧要)。

问题是当我迁移我的数据时,它成功迁移到本地 iCloud 存储并成功停止监听 iCloud 通知。这方面有效,这是我之前提出的堆栈溢出问题 (Migrate iCloud data to Local store and stopping iCloud from still responding)。

具体问题是,当用户重新启动应用程序时,应用程序现在是空的,没有数据。这当然不是想要的效果。

为了完整起见,“迁移代码”基于另一个堆栈溢出问题,但为了方便起见,我将其粘贴在这里:

- (void)migrateiCloudStoreToLocalStore {

NSLog(@"Migrate iCloudToLocalStore");
NSPersistentStore *store = self.persistentStoreCoordinator.persistentStores.lastObject;

//NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"Envylope.sqlite"];
NSURL *storeURL = [self.persistentStoreCoordinator.persistentStores.lastObject URL];
NSLog(@"Current Store URL (before iCloud to Local migration): %@", [storeURL description]);

NSDictionary *localStoreOptions = nil;
localStoreOptions = @{ NSPersistentStoreRemoveUbiquitousMetadataOption : @YES,
NSMigratePersistentStoresAutomaticallyOption : @YES,
NSInferMappingModelAutomaticallyOption : @YES};

NSPersistentStore *newStore = [self.persistentStoreCoordinator migratePersistentStore:store
toURL:storeURL
options:localStoreOptions
withType:NSSQLiteStoreType error:nil];

[self reloadStore:newStore];
}

- (void)reloadStore:(NSPersistentStore *)store {
NSLog(@"Reload Store");
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"Envylope.sqlite"];
NSDictionary *localStoreOptions = nil;
localStoreOptions = @{ NSPersistentStoreRemoveUbiquitousMetadataOption : @YES,
NSMigratePersistentStoresAutomaticallyOption : @YES,
NSInferMappingModelAutomaticallyOption : @YES};

if (store) {
[self.persistentStoreCoordinator removePersistentStore:store error:nil];
}

[self.persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:storeURL
options:localStoreOptions
error:nil];
storeURL = [self.persistentStoreCoordinator.persistentStores.lastObject URL];
NSLog(@"Current Store URL (after iCloud to Local migration): %@", [storeURL description]);

NSLog(@"Done reloading");

[[NSUserDefaults standardUserDefaults]setBool:YES forKey:@"MigratedFromiCloudToLocal"];
[[NSUserDefaults standardUserDefaults]synchronize];

所有的魔法都发生在 persistentStoreCoordinator 中。它很乱,但我需要让这部分工作,然后才能清理它:

    - (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (_persistentStoreCoordinator != nil) {
return _persistentStoreCoordinator;
}

NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"Envylope.sqlite"];

NSError *error = nil;

NSURL *iCloud = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier: nil];
NSDictionary *options = nil;

if ((iCloud) && (![[NSUserDefaults standardUserDefaults] boolForKey:@"iCloudOn"]) && (![[NSUserDefaults standardUserDefaults]boolForKey:@"OnLatestVersion"]))
{
NSLog(@"In the persistent store, iCloud is enabled in the app device but not yet in the app and not on the latest version");

options = @{ NSMigratePersistentStoresAutomaticallyOption : @YES,
NSInferMappingModelAutomaticallyOption : @YES};

}
else if ((iCloud) && ([[NSUserDefaults standardUserDefaults] boolForKey:@"iCloudOn"]) && ([[NSUserDefaults standardUserDefaults]boolForKey:@"OnLatestVersion"]))
{
NSLog(@"In the persistent store, iCloud is enabled, we're using iCloud from the Tutorial and we're on the latest version");
NSURL *cloudURL = [self grabCloudPath:@"iCloud"];
options = @{ NSMigratePersistentStoresAutomaticallyOption : @YES,
NSInferMappingModelAutomaticallyOption : @YES,
NSPersistentStoreUbiquitousContentURLKey: cloudURL, NSPersistentStoreUbiquitousContentNameKey: @"EnvyCloud"};


}
else if ((iCloud) && (![[NSUserDefaults standardUserDefaults] boolForKey:@"iCloudOn"]) && ([[NSUserDefaults standardUserDefaults]boolForKey:@"OnLatestVersion"]))
{
NSLog(@"In the persistent store, iCloud is enabled, we're on the latest version, btu we're not using icloud in the App");

options = @{ NSMigratePersistentStoresAutomaticallyOption : @YES,
NSInferMappingModelAutomaticallyOption : @YES};

}
else
{
NSLog(@"iCloud is just not enabled");

options = @{ NSMigratePersistentStoresAutomaticallyOption : @YES,
NSInferMappingModelAutomaticallyOption : @YES};

}

_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];

if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error]) {

NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
//abort();
}
return _persistentStoreCoordinator;
}

因此,在用户在应用程序中启用 iCloud 然后决定不再在此特定设备上使用 iCloud 的情况下,iCloud 通知将被删除,商店从 iCloud 商店迁移到本地商店并且 NSUserDefaults 是放。在下次启动该应用程序时,第三个 if 语句在 persistentStoreCoordinator 中的计算结果为真,这正确地说我们使用的是最新版本,iCloud 已启用(在设备中)但未在应用程序,但随后它显示该应用程序完全没有任何条目,有点像重新开始。

我该如何克服这个问题并返回最近迁移的商店?

如有任何想法,我们将不胜感激。

最佳答案

应用程序启动时没有数据指向持久存储协调器。

看起来对选项字典的评估很好,但在任何一种结果中,您总是使用相同的持久存储 URL 设置协调器。

同样,在迁移例程中,您正在迁移持久存储对象,但使用相同的 URL。那是行不通的,因为那是保存实际文件的地方。您需要为本地商店和 iCloud 商店使用不同的 URL,然后您可以正确地迁移数据并选择删除不再需要的 URL(从协调器中删除商店后)。

根据您的评估结果,使用相应的 URL 设置协调器 - 希望 - 您应该在应用启动时看到您的数据。

关于ios - 将 iCloud 商店迁移到本地商店并确保数据在每次应用程序启动时都在那里,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25204640/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com