核心数据iOS 8今日小部件问题

4

我有一个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 方法,然后逐个修改项目。例如:set item.itemName = @"testName"; 然后调用我的 save 方法。
我还有一个 iOS 8,其中在我的 TodayViewController 中也调用了 getItems 方法。我有一个 NSNotification,检测 managedObjectContext 是否已保存。
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(refetchItems) name:NSManagedObjectContextDidSaveNotification object:[[DataManager sharedInstance] managedObjectContext]];

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

我做错了什么?如果您需要查看其他代码,请告诉我。

谢谢!


@quellish,那么检测变化的最佳方法是什么? - Stephen
1
我也有完全相同的问题,但是我也没有找到解决方案。唯一能想到的方法就是“销毁”上下文并重新创建它。 - Martin Perry
你确定你没有听到任何 DidChange 通知吗? - Léo Natan
@LeoNatan 我确实收到了DidChange通知。 仅仅重新获取不会让我得到更新后的对象。 奇怪的是,它确实可以检测到我添加了新对象或删除了一些对象。 - Stephen
@user132490 我正在为你寻找一种解决方案。正如Martin所指出的,您必须销毁您的上下文(context),创建新的上下文并重新获取以获得正确的行为。否则,您将继续获得过时的值,并且如果从持久存储中删除对象,则有崩溃的风险。如果您仅重置您的上下文(context),则可能仍会超保留已删除的托管对象,并存在崩溃风险。 - quellish
显示剩余5条评论
1个回答

7
您可以尝试以下方法来刷新特定的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;

在我的课程中,我手动创建了setter。如果我将所有变量设为"nill",由于setter,它们会在我在核心数据管理类之外读取它们时再次初始化。

您可以通过使用NSUserDefault存储来改善这种情况。它会被正确地更新。在主应用程序中,如果更改了某些内容,则在NSUserDefault中设置标志。在扩展中,读取此标志,如果标志已标记,则重置核心数据。通过这种方式,您将节省一些时间并使事情变得快一点。

对于NSUserDefault的分配(在扩展和主应用程序中),请使用以下代码-之后,您可以像通常一样从中读取数据,并且它们应该同步。

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接