@Edit @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"
接下来我收到购物车数据以便退货。同样如您所建议的那样,不使用特定的上下文
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:
完成阻止返回success = true, error = nil
在此操作之后,我们正在刷新购物车
let cart: Cart? = Cart.mr_findFirst()
- cart.entries字段有两个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
答案 0 :(得分:0)
MagicalRecord.save
正在将数据保存到defaultContext
MagicalRecord.save({ (context) in
_ = data(context)
}) { (success, error) in
completion(success,error)
}
,而self.localContext
为mr_rootsaving
??
快速建议:
使用MagicalRecord.setupCoreDataStack(withAutoMigratingSqliteStoreNamed: dataStack)
代替MagicalRecord.setupCoreDataStack(withStoreNamed: dataStack)
。始终让MagicalRecord为您处理autoMigration。
在大多数情况下,我习惯使用MagicalRecord
始终坚持使用defaultContext
。对于您的用例,如果您始终使用self.localContext
(将数据保存到MagicalRecord.save
)保存数据,则您实际上无需明确创建defaultContext
。然后,您只需使用let cart: Cart? = Cart.mr_findFirst()
随时随地检索所需的数据。
更新回答
感谢您更新@PiotrGawłowski的问题。
为什么有:上下文?因为当我省略它们时保存不是 执行。我有一个警告:没有变化** saveWithBlock:完成:**上下文 - 不保存
MagicalRecord.save({(context)..
创建一个新的上下文,用于在闭包中执行操作,然后它合并回defaultContext
。正如我之前提到的,如果您没有明确指定上下文,MagicalRecord
将回退到defaultContext
。因此,如果您没有添加“inContext:”,那么您在defaultContext
块内的MagicalRecord.save({(context)..
中创建了一个实体。事实证明,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
操作一切正常吗?剩下的问题是deletion
。首先,尝试2 是我上面提到的上下文问题。
所以让我们专注于
效果1:完成块返回成功= true,错误= nil在此操作之后我们正在使用cart:cart刷新购物车? = Cart.mr_findFirst() - cart.entries字段有2个CartEntry对象,忽略了我刚删除的事实。什么是更多的应用程序崩溃,因为收到的条目(一个应该被删除)没有相关的产品。 CoreDataEditor仅显示1个条目。重新启动应用程序后,购物车再次正确 - 只有1个条目,没有我刚刚删除的数据。
delete
来电似乎没问题
应用程序崩溃是您实际删除条目的一个好兆头
您重新启动了该应用,只剩下一个条目,证明您的 删除声明完成了它的工作
(您是否使用CoreDataEditor
仔细检查结果?)
所以我们可以确认所有其他部分都正常工作,唯一的问题似乎是您没有正确处理数据源更改。你使用的是UITableView
吗?您是否使用NSFetchedResultsControllerDelegate
扩展了课程并实施了委托方法?
请告诉我们该部分的代码。 (用于显示数据的ViewController)。