Core Data iOS 8 Today Widget 问题

Posted

技术标签:

【中文标题】Core Data iOS 8 Today Widget 问题【英文标题】:Core Data iOS 8 Today Widget issue 【发布时间】:2014-09-18 23:49:00 【问题描述】:

我有一个返回共享实例的 DataManager 类:

+ (DataManager *)sharedInstance;

    static DataManager *sharedInstance = nil;
    static dispatch_once_t pred;

    dispatch_once(&pred, ^
        sharedInstance = [[DataManager alloc] init];
    );

    return sharedInstance;

在这里我跟踪我的 managedObjectContext、managedObjectModel、persistentStoreCoordinator。

我还有一种方法可以取出项目进行展示:

- (NSArray *)getItems

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"Item"];
    return [[self managedObjectContext] executeFetchRequest:fetchRequest error:nil];

现在在我的主应用程序中,当我调用此 getItems 然后单独修改项目时,我有一个视图控制器。例如设置 item.itemName = @"testName";然后调用我的保存方法。

我还有一个 ios 8,在 TodayViewController 中我还调用了 getItems 方法。我有一个检测 managedObjectContext 保存的 NSNotification。

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(refetchItems) name:NSManagedObjectContextDidSaveNotification object:[[DataManager sharedInstance] managedObjectContext]];

这些重新获取的项目确实会被调用,但会返回过时的 NSManagedObjects。因此,例如 itemName 没有更改为 @"testName"。

我哪里错了?如果您需要查看任何其他代码,请告诉我。

谢谢!

【问题讨论】:

您的应用和小部件在不同的进程中运行。如果您的应用更改了核心数据存储,您的小部件将不会收到应用发送的通知。 @quellish 那么检测变化的最佳方法是什么? 我也有同样的问题,但也没有找到解决办法。只有我能想到的,就是“破坏”上下文并重新创建它。 您确定您没有听到任何DidChange 通知吗? @LeoNatan 我实际上听到了 DidChange 通知。只是重新获取不会让我得到更新的对象。奇怪的是,它确实检测到我添加的新对象或我删除了一些对象。 【参考方案1】:

您可以尝试以下方法来刷新特定的 ManagedObject。如果要刷新 ManagedObject 列表,则循环每个对象并执行命令。

[_managedObjectContext refreshObject:act mergeChanges:YES];

或者对于 iOS 8.3 及以上版本,您可以使用以下方法一次更新上下文中的所有 ManagedObject,如下所示。

[_managedObjectContext refreshAllObjects];

它有点作用,但只用于数据更新,不能用于添加或删除数据。

如果不工作,你也可以添加

[_managedObjectContext reset];

之后,您必须读取“重新分配”所有从核心数据存储中加载的变量。

另一种解决方案(更慢更丑)

如果上述方法不起作用,另一种解决方案是删除当前上下文并重新创建它。

我只是设置了

_persistentStoreCoordinator = nil;
_managedObjectModel = nil;
_managedObjectContext = nil;

我有具有此属性的 CoreDataManager 类

@property (nonatomic, retain, readonly) NSManagedObjectModel *managedObjectModel;
@property (nonatomic, retain, readonly) NSManagedObjectContext *managedObjectContext;
@property (nonatomic, retain, readonly) NSPersistentStoreCoordinator *persistentStoreCoordinator;

在课堂上,我手动创建了设置器。如果我将所有变量都归零,由于设置器,一旦我在核心数据管理器类之外读取它们,它们就会再次被初始化。

您可以通过使用NSUserDefault 商店来改善这一点。它正在正确更新。在主应用程序中,如果您更改某些内容,请在NSUserDefault 中设置标志。在扩展中,阅读此内容,如果标记了标志,则重置核心数据。这样,您将节省一些滴答声并加快速度。

对于NSUserDefault 的分配(在两个应用程序 - 扩展和主)使用这个 - 之后,您可以像往常一样从中读取数据并且它们应该是同步的

NSUserDefaults *prefs = [[NSUserDefaults alloc] initWithSuiteName:GROUP_NAME]; //share with extension

【讨论】:

以上是关于Core Data iOS 8 Today Widget 问题的主要内容,如果未能解决你的问题,请参考以下文章

将数据从Core Data加载到Today Widget

将数据从 Core Data 加载到 Today Widget

UISearchController 和 UITableView 支持 Core Data iOS 8

从 Core Data iOS 8 中删除二进制数据

iCloud Core Data 在 Xcode 6 / ios 8 SDK 中运行后不可用

在 iOS 8 Today Extensions 中拖动手势