【问题标题】:Crash after reseting NSPersistentStore while NSFetchedResultsController is tracking changed在 NSFetchedResultsController 跟踪更改时重置 NSPersistentStore 后崩溃
【发布时间】:2012-03-03 00:11:11
【问题描述】:

这是我想要做的:

  1. 我使用 NSFetchedResultsController 执行获取并使用其委托跟踪更改
  2. 我下载了一些数据,根据某些情况,我有时会通过删除 NSPersistentStore 并重新创建一个新数据来删除 CoreData 存储的所有本地数据。
  3. 我根据数据创建托管对象并保存它们
  4. NSFetchedResultsController 现在应该通知我我有一些更改

我得到的是尝试保存数据时的崩溃:

CoreData:错误:严重的应用程序错误。在核心数据更改处理期间捕获到异常。这通常是 NSManagedObjectContextObjectsDidChangeNotification 观察者中的一个错误。使用 userInfo (null) 的 NSManagedObjectContext 协调器无法访问对象的持久存储

我总是使用单个 NSManagedObjectContext 并且我总是在主线程上读取和保存。

似乎切换 NSPersistenStore 会以某种方式弄乱获取的结果控制器。这是预期的行为还是我做错了什么?

【问题讨论】:

    标签: iphone objective-c ios core-data nsfetchedresultscontroller


    【解决方案1】:

    我不会推荐这种方法。我会用你的新持久存储创建一个新的 MOC 并放弃旧的 MOC。

    我假设你在某个时候打电话给-[ManagedObjectContext reset]?在你这样做之前,你必须放弃来自那个上下文的所有托管对象。它们都变得无效(这可能是您崩溃的原因)。

    你也应该看看How to force coredata to rebuild sqlite database model?

    【讨论】:

    • 也尝试过重置;仍然没有变化。我已经使用removePersistentStore:error addPersistentStoreWithType:configuration:URL:options:error 删除/添加持久存储。如果我需要重新创建 MOC,那么我认为我也必须重新创建 NSFetchedResultsController;我试图避免这种情况以减少应用程序中的耦合
    • 是的,我相信删除 NSFetchedResultsController 将是解决方案的核心。我想不出一种方法来提取所有数据(无需通过调用deleteObject: 获得更改通知),同时保留引用该数据的对象。
    • 理论上,一旦 NSFetchedResultsController 的底层存储消失,它的结果集中的所有对象都被删除了,MOC 就可以通知 NSFetchedResultsController。不知道这是如何在内部处理的。
    • @RobNapier,我需要你的帮助,我在从 coreData 重置所有数据时遇到问题。这是我的问题stackoverflow.com/questions/19358095/core-data-reset
    【解决方案2】:

    我遇到了同样的崩溃。按照 Rob 的建议,我每次调用 removePersistentStore: 时都会另外发布一个 NSNotification - 我的所有具有 NSFetchedResultController 的 ViewController 现在会在发生这种情况时自动取消其本地 NSFetchedResultsController。

    即:

    1 - 听取通知:

    -(id)initWithCoder:(NSCoder *)aDecoder
    {
        self = [super initWithCoder:aDecoder];
        if (self) {
        // Custom initialization
        [[NSNotificationCenter defaultCenter] addObserverForName:kNotificationDestroyAllNSFetchedResultsControllers object:nil queue:nil usingBlock:^(NSNotification *note) {
            NSLog(@"[%@] must destroy my nsfetchedresultscontroller", [self class]);
            [__fetchedResultsController release];
            __fetchedResultsController = nil;
            }];
        }
        return self;
    }
    

    2 - 发布通知

    for( NSPersistentStore* store in [self.persistentStoreCoordinator persistentStores] )
    {
        NSError *error;
        NSURL *storeURL = store.URL;
        [self.persistentStoreCoordinator removePersistentStore:store error:&error];
        [[NSFileManager defaultManager] removeItemAtPath:storeURL.path error:&error];
    
        /** ... side effect: all NSFetchedResultsController's will now explode  */
        [[NSNotificationCenter defaultCenter] postNotificationName:kNotificationDestroyAllNSFetchedResultsControllers object:self];
    }
    

    【讨论】:

      【解决方案3】:

      NSFetchedResultsController 监控其关联托管对象上下文中对象的更改,因此它可能正在监控已过时托管对象上下文中对象的更改。

      当我在重置 NSPersistentStore 后重新创建 NSFetchedResultsController 时,这个问题得到了解决

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-06-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多