@编辑 @PangHoMing - 我会再次一步一步地做。 首先设置 - 按照您的建议
MagicalRecord.setLoggingLevel(.verbose)
MagicalRecord.setupCoreDataStack(withAutoMigratingSqliteStoreNamed: dataStack)
下一个数据保存方法:
MagicalRecord.save({ (context) in
_ = data(context)
}) { (success, error) in
completion(success,error)
}
我正在使用CoreDataEditor
预览实体。执行完这部分后,一切似乎都很好。
购物车创建闭包(我刚刚删除了负责特定字段的部分以缩短消息)
let createCart: (NSManagedObjectContext) -> () = {context in
let offlineCart = Cart.mr_createEntity(in: context)!
offlineCart.code = "0"
接下来我将取 repo 物车数据以将其返回。也正如您所建议的,不使用特定上下文
let cart: Cart? = Cart.mr_findFirst()
现在让我们将某物添加到我的购物车,这里开始一些有问题的部分
let addEntry: (NSManagedObjectContext) -> () = { context in
if let entry = CartEntry.mr_findFirst(with: NSPredicate(format: "product.code == %@", productCode), in: context) {
entry.quantity = NSNumber.init(value: (entry.quantity?.intValue)! + 1)
} else {
let entry = CartEntry.mr_createEntity(in: context)!
entry.quantity = quantity
entry.product = Product.mr_findFirst(with: NSPredicate(format: "code == %@", productCode), in: context)
entry.code = productCode
entry.cart = Cart.mr_findFirst(in: context)
}
}
正如您所看到的,上面的代码正在尝试查找现有的 CartEntry
如果发现它只是增加数量,如果没有则创建新的 CartEntry
相关于Cart
和Product
。为什么会有in: context
?因为当我忽略它们时,保存不会执行。我收到如下警告:NO CHANGES IN ** saveWithBlock:completion: ** CONTEXT - NOT SAVING
到目前为止,一切似乎都还不错。 CoreDataEditor
显示这样的结构
现在让我们进行删除操作。
尝试 1 - 删除传递给 save 方法的闭包(如上所述)
let removeEntry: (NSManagedObjectContext) -> () = { context in
CartEntry.mr_deleteAll(matching: NSPredicate(format: "product.code == %@", product.code), in: context)
}
self.coreDataManager.saveData(data: removeEntry, completion: { (succes, error) in
completion(succes, error)
})
效果1:
竣工区 block 返回success = true, error = nil
执行此操作后,我们立即刷新购物车
let cart: Cart? = Cart.mr_findFirst()
- cart.entries 字段有 2 CartEntry
对象忽略了我刚刚删除了一个这一事实。更重要的是,应用程序崩溃是因为收到的条目(应该删除的条目)没有相关Product
。 CoreDataEditor
仅显示 1 个条目。重新启动应用程序后,购物车再次正确 - 只有 1 个条目,没有我刚刚删除的数据。
尝试 2:
让我们忽略in: context
let removeEntry: (NSManagedObjectContext) -> () = { context in
CartEntry.mr_deleteAll(matching: NSPredicate(format: "product.code == %@", product.code))
}
效果2:
NO CHANGES IN ** saveWithBlock:completion: ** CONTEXT - NOT SAVING
解决方案
仔细检查您的Delete rules
- 问题是 No Action
而不是Nullify
最佳答案
MagicalRecord.save
正在将数据保存到 defaultContext
MagicalRecord.save({ (context) in
_ = data(context)
}) { (success, error) in
completion(success,error)
}
而你的self.localContext
是mr_root saving
??
快速建议:
使用
MagicalRecord.setupCoreDataStack(withAutoMigrationSqliteStoreNamed: dataStack)
而不是MagicalRecord.setupCoreDataStack(withStoreNamed: dataStack)
。始终让 MagicalRecord 为您处理自动迁移。在大多数情况下,我使用
MagicalRecord
的习惯始终坚持使用defaultContext
。对于您的用例,如果您始终使用MagicalRecord.save
保存数据(它将数据保存到defaultContext 中),您确实不需要显式创建
)。然后你可以简单地使用self.localContext
let cart: Cart? = Cart.mr_findFirst()
随时随地检索您需要的数据。
更新答案
感谢您更新问题@Piotr Gawłowski。
Why there are in: context? Cause when I omit them save is not performing. I've got a warnings like:NO CHANGES IN ** saveWithBlock:completion: ** CONTEXT - NOT SAVING
MagicalRecord.save({(context)..
创建一个新的上下文来执行闭包中的操作,然后它合并回 defaultContext
。正如我提到的之前,如果您没有显式指定上下文,MagicalRecord
将回退到 defaultContext
。因此,如果您没有添加“inContext:”,则发生的情况是您创建的MagicalRecord.save({(context)..
block 内的 defaultContext
中的实体。事实证明,MagicalRecord 的上下文没有发生任何更改。 save({(context).
(我的英语很烂,但我知道你很聪明能理解)
并且,您可以使用mr_findFirstOrCreate
初始化程序
let addEntry: (NSManagedObjectContext) -> () = { context in
let entry = CartEntry.mr_findFirstOrCreate(with: NSPredicate(format: "product.code == %@", productCode), in: context) {
entry.quantity = NSNumber.init(value: (entry.quantity?.intValue)! + 1)
entry.product = Product.mr_findFirst(with: NSPredicate(format: "code == %@", productCode), in: context)
entry.code = productCode
entry.cart = Cart.mr_findFirst(in: context)
}
言归正传,基本上 add
和 fetch
操作都工作正常,对吗?剩下的问题是删除
。首先,尝试2就是我上面提到的上下文问题。
所以让我们关注
Effect 1: Completions block returns success = true, error = nil Right after this operations we're refreshing cart with let cart: Cart? = Cart.mr_findFirst() - cart.entries field got 2 CartEntry objects ignoring fact that I just deleted one. What is more app crashes because received entry (one that supposed to be deleted) do not have related Product. CoreDataEditor shows only 1 entry. After restarting applications cart is once again correct - got only 1 entry, without data I just deleted.
您的
delete
调用似乎没问题应用程序崩溃是您实际上删除了该条目的好兆头
您重新启动了应用程序,只剩下 1 个条目,证明您的 删除语句完成了它的工作
(您是否使用CoreDataEditor
仔细检查结果?)
因此我们可以确认所有其他部分都正常工作,唯一的问题似乎是您没有正确处理数据源更改。您使用的是 UITableView
吗?您是否使用 NSFetchedResultsControllerDelegate
扩展您的类并实现委托(delegate)方法?
请告诉我们该部分的代码。 (用于显示数据的 ViewController)。
关于ios - MagicalRecord - 保存后数据错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42980169/