gpt4 book ai didi

ios - 后台上下文保存导致 NSFetchedResultsController didChange anObject 调用 .delete 而不是 .update

转载 作者:行者123 更新时间:2023-11-28 09:29:04 26 4
gpt4 key购买 nike

我在 UICollectionView 中使用 NSFetchedResultsController。

问题:当用户打开 View 时,我向 API 发送请求并在后台使用 performBackgroundTask() 解析响应。 NSFetchedResultsController 将正确加载托管对象,但在我解析数据并调用 context.save() 后,didChangeObject 方法被调用 NSFetchedResultsChangeType.delete 但之后既不调用 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') 它将按预期工作。当然,这仅适用于具有该标题的一个对象,但它将成功保存上下文、合并更改并更新集合,正如我所期望的那样。

最佳答案

问题出在您的谓词格式。您正在尝试做的是为当前用户 查找Feed 对象并且您正在编写它:-

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

但这是一个错误

从技术上讲,user 是一个 Core-Data 条目,但 predicate 不直接使用 Core-Data 实体进行验证。 Predicate 可以验证字符串、整数、 bool 值、日期类型的值。

所以解决方案是将您的查询修改为如下内容:-

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

我假设 id 是您的用户表中的主键。因此,请务必将 id 替换为用户表中的唯一键。希望对您有所帮助。

关于ios - 后台上下文保存导致 NSFetchedResultsController didChange anObject 调用 .delete 而不是 .update,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46381999/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com