【发布时间】:2025-12-27 03:20:21
【问题描述】:
亲爱的 Stack Overflow 人,
我已经使用 Core Data 和 iCloud 构建了一个应用程序。这是UITabBarController 中的一个简单的 4 选项卡,每个选项卡都是 UITableViewController。第一个选项卡名为 Timeline,然后是 Person、Event 和 Date。
使用设备 1,当控制台中显示“Using local storage: 0”时,我添加了一些条目。当我建立第二台设备(在同一个 iCloud 帐户上)(iPad)时,它以Using Local Storage: 1(预期)开始,然后是0(预期)。但是,Timeline 选项卡(主视图)实际上并未显示新条目,但 Person、Event 和 Date 选项卡确实正确显示了它。如果我重新启动该应用程序,它就会出现在时间轴中。
我为每个UITableViewController 使用NSFetchedResultsController,并参考了一个优秀的教程(http://pinkstone.co.uk/how-t-use-icloud-in-your-ios-apps/),在我的时间轴中,我输入了以下代码:
- (void)viewDidLoad
{
[super viewDidLoad];
// add iCloud observers
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(storesWillChange) name:NSPersistentStoreCoordinatorStoresWillChangeNotification object:self.managedObjectContext.persistentStoreCoordinator];
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(storesDidChange:) name:NSPersistentStoreCoordinatorStoresDidChangeNotification object:self.managedObjectContext.persistentStoreCoordinator];
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(mergeContent:) name:NSPersistentStoreDidImportUbiquitousContentChangesNotification object:self.managedObjectContext.persistentStoreCoordinator];
}
#pragma mark - iCloud Methods
- (void)storesWillChange {
NSLog(@"\n\nStores WILL change notification received\n\n");
// disbale UI
[[UIApplication sharedApplication]beginIgnoringInteractionEvents];
// save and reset our context
if (self.managedObjectContext.hasChanges) {
[self.managedObjectContext save:nil];
} else {
[self.managedObjectContext reset];
}
}
- (void)storesDidChange:(NSNotification *)notification {
NSLog(@"\n\nStores DID change notification received\n\n");
// enable UI
[[UIApplication sharedApplication]endIgnoringInteractionEvents];
// update UI
[self.timelineTableView reloadData];
}
- (void)mergeContent:(NSNotification *)notification {
NSLog(@"!Merge Content here!");
[self.managedObjectContext mergeChangesFromContextDidSaveNotification:notification];
}
我注意到一些奇怪的事情。
为清晰而编辑 1) iPad(第二台设备)在初始导入期间或任何后续同步期间从不运行storesWillChange 或storesDidChange。
2) iPad 的人员/事件选项卡已填充,但时间轴未填充。只有当我重新运行应用程序或从设备 1 添加新条目时,iPad 的时间轴才会更新。
问题
当 iPad 第一次连接到 iCloud 时,我需要做什么才能让 iPad 在时间轴选项卡中显示数据?这不是耐心的问题,因为我等了 43 分钟没有任何变化。
当来自 iCloud 的数据很重要时,在第二台设备上运行的方法是什么?这是我的钥匙。如果是storesDidChange,我应该把它放在哪里?我已经尝试将通知侦听器放置在viewDidLoad Timeline View Controller、App Delegate 中的 applicationDidFinishLaunchingWithOptions 和 NSManagedObjectContext 中,但在任何这些情况下它都不会运行。
这是一个仅限 iOS 7 的应用程序。
编辑:进一步更新
我现在已经到了 iPad(第二台设备)仍然不显示 iCloud 数据的地步,但是如果我在第一台设备上添加一个新条目,它就会合并内容并同步。
今天早上多次阅读 Apple 指南:https://developer.apple.com/library/prerelease/ios/documentation/DataManagement/Conceptual/UsingCoreDataWithiCloudPG/UsingSQLiteStoragewithiCloud/UsingSQLiteStoragewithiCloud.html#//apple_ref/doc/uid/TP40013491-CH3-SW4,我可以看到在添加持久存储之前注册 storesDidChange 很重要。这是有道理的,我这样做了,我从 storesDidChange 方法中获取了 NSLog。
但是,在 One Time Ubiquity Store Container 完成设置后,它应该再次运行 storesWillChange 通知以及 storesDidChange。
在我的情况下两者都没有运行。
参考这个页面,这似乎正是我在这里面临的问题:http://www.zx81.org.uk/computing/programming/nsfetchedresultscontroller-and-icloud.html,用户在 UITableView 中重新获取。我正在这样做,但仍然,数据不会出现在 iPad 上,这是第一次运行并与 iCloud Store 同步。
但是,因为它是 UITabBarController,所以其他选项卡正在适当更新。只是这个选项卡,在从回退到 iCloud 商店迁移之前和之后已经显示。
编辑:在此处添加persistentStoreCoordinator 方法
如果问题出在我的 persistentStoreCoordinator 上,我将在此处添加该代码:
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
NSLog(@"Persistent Store");
if (_persistentStoreCoordinator != nil) {
return _persistentStoreCoordinator;
}
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"Envylope.sqlite"];
NSError *error = nil;
// get a reference to your iCloud URL
NSURL *cloudURL = [self grabCloudPath:@"iCloud"];
// setup options depending on migration
NSDictionary *options = nil;
if ([[NSUserDefaults standardUserDefaults]boolForKey:@"OnLatestVersion"]) {
options = @{ NSMigratePersistentStoresAutomaticallyOption : @YES,
NSInferMappingModelAutomaticallyOption : @YES,
NSPersistentStoreUbiquitousContentURLKey: cloudURL, NSPersistentStoreUbiquitousContentNameKey: @"EnvyCloud"};
NSLog(@"Using iCloud from migration");
}
else
{
NSLog(@"Using the other store without the iCloud Migration");
options = @{ NSMigratePersistentStoresAutomaticallyOption : @YES,
NSInferMappingModelAutomaticallyOption : @YES};
}
NSLog(@"Just before adding the persistent store");
_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();
}
NSLog(@"Just after adding the store");
return _persistentStoreCoordinator;
}
我有 if 语句和 userDefaults 的原因是因为我想检查用户的应用程序是否需要迁移到新版本并在应用程序再次运行时维护该版本。我的意思是,如果我的设备上有带有数据的 App Store 版本并更新到这个 iCloud 版本,它会将数据迁移到 iCloud 商店。如果我再次运行该应用程序,它不会再次迁移,它只是使用 iCloud 商店。这可以进行同步,虽然我不认为这是问题所在(因为其他设备确实会在其他选项卡上获取云信息),但它已经完成了。
任何通往正确方向的路径都会非常有帮助。
【问题讨论】:
-
只是澄清一下:其他三个选项卡是否也从同一个 iCloud 核心数据堆栈更新?它们是否按预期更新?
-
非常感谢 Jay - 其他三个选项卡来自同一个 iCloud 核心数据堆栈,它们只是第一次表示相同的数据,但只是使用特定谓词来显示略有不同的结果。当我在第二个设备中运行此连接过程时,在控制台中显示“使用本地存储:0”后,第二个设备会立即使用来自第一个设备的正确数据更新它的第二个、第三个和第四个选项卡。这只是第一个选项卡(根视图)没有。谢谢!
标签: ios iphone core-data notifications icloud