2017-09-23 21 views
1

我在UICollectionView中使用NSFetchedResultsController。後臺上下文保存導致NSFetchedResultsController didChange anObject調用.delete而不是.update

問題:當用戶打開視圖時,我向API發送一個請求,並使用performBackgroundTask()解析背景中的響應。 NSFetchedResultsController將正確加載託管對象,但是在我解析數據並調用context.save()後,將使用NSFetchedResultsChangeType.delete調用didChangeObject方法,但在此之後既不會調用update也不會調用insert

這是一些代碼。

解析和保存

static func parse(withJSON json: [JSON]) { 
    let container = (UIApplication.shared.delegate as! AppDelegate).persistentContainer 

    container.performBackgroundTask() { (context) in 
     context.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy 

     for feedJSON in json { 
      if let feedID = feedJSON["_id"].string { 
       let feed = Feed.getWithId(id: feedID, withContext: context) ?? (NSEntityDescription.insertNewObject(forEntityName: "Feed", into: context) as! Feed) 
       feed.update(withJSON: feedJSON, withContext: context) 
      } 
     } 

     do { 
      try context.save() 
     } catch { 
      fatalError("Failure to save context: \(error)") 
     } 
    } 
} 

視圖背景

lazy var persistentContainer: NSPersistentContainer = {   
    let container = NSPersistentContainer(name: "TheApp") 
    container.loadPersistentStores(completionHandler: { (storeDescription, error) in 

     if let error = error as NSError? {     
      #if DEVELOPMENT 
       fatalError("Unresolved error \(error), \(error.userInfo)") 
      #endif 
     } 
    }) 

    container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy 
    container.viewContext.automaticallyMergesChangesFromParent = true 
    container.viewContext.retainsRegisteredObjects = true 

    return container 
}() 

初始化NSFetchedResultsController

func initializeFetchedResultsController() { 
    guard let user = Current.user else { 
     return 
    } 

    let request: NSFetchRequest<Feed> = Feed.fetchRequest() 
    let createdAtSort = NSSortDescriptor(key: "createdAt", ascending: false) 
    request.sortDescriptors = [createdAtSort] 
    request.predicate = NSPredicate(format: "author = %@", user) 

    let moc = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext 

    resourceFetchedResultsController = NSFetchedResultsController(fetchRequest: request, managedObjectContext: moc, sectionNameKeyPath: nil, cacheName: nil) 
    resourceFetchedResultsController?.delegate = self 

    do { 
     try resourceFetchedResultsController?.performFetch() 
    } catch { 
     fatalError("Failed to initialize FetchedResultsController: \(error)") 
    } 
} 

author與管理對象User是一對一的關係。我已經驗證過,在保存背景上下文時不會以某種方式刪除它。我還將Feed.author關係的刪除規則更改爲No ActionNullifyCascade,但沒有任何更改。

對象更改通知

最後,我設置的通知聽在環境的變化。它在performBackgroundTask()中的每個context.save()之後成功調用,但它只有關於正在更新的對象的信息,並且從不刪除。

NotificationCenter.default.addObserver(self, selector: #selector(managedObjectContextObjectsDidChange), name: NSNotification.Name.NSManagedObjectContextObjectsDidChange, object: nil) 

NotificationCenter.default.addObserver(self, selector: #selector(managedObjectContextObjectsDidChange), name: NSNotification.Name.NSManagedObjectContextWillSave, object: nil) 

NotificationCenter.default.addObserver(self, selector: #selector(managedObjectContextObjectsDidChange), name: NSNotification.Name.NSManagedObjectContextDidSave 

是沒有工作的一個事情...

當我改變從NSPredicate(format: "author = %@", user)謂詞NSPredicate(format: "title = %@", 'My Title')它會正常工作。當然,這隻適用於具有該標題的一個對象,但它會成功保存上下文,合併更改並按照我的預期更新集合。

+0

當您檢查已更新的對象時,'author'屬性的值是多少?如果它不是'Current.user',FRC將觸發刪除委託調用:由於對象不再與謂詞相匹配,因此必須刪除相應的collectionView單元格。 – pbasdf

+0

是的,我也想到了,但更新後,作者對象仍然是'Current.user' – Sonny

回答

-1

問題是您的謂詞格式。你所要做的是找到飼料爲當前用戶對象和你正在寫它: -

NSPredicate(format: "author = %@", user) 

但它是一個錯誤

技術上用戶是核心,數據輸入,但謂詞不直接與Core-Data實體進行驗證。謂詞可以用字符串,整數,布爾值,日期類型值進行驗證。

因此,解決辦法是修改你的查詢是這樣的: -

NSPredicate(format: "author.id = %@", user.id) 

如果我假設ID是在用戶表的主鍵。所以請務必用您的用戶表中的唯一密鑰替換ID。我希望這個幫助。

+0

'author'是一個與NSManagedObject類型的關係,並且是根據文檔https://developer.apple.com/library /content/documentation/Cocoa/Conceptual/Predicates/Articles/pUsing.html請參閱「使用連接」一節,它在其中表示「測試對象相等比測試源對象的屬性更有效」。不幸的是,改爲'author.id =%@'不起作用,導致'libC++ abi.dylib:以NSException類型的未捕獲異常終止。 – Sonny

相關問題