MagicalRecord - 保存后的错误数据

时间:2017-03-23 15:17:54

标签: ios swift core-data magicalrecord

@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,如果发现它只是增加数量,如果不是,它会创建与CartEntryCart相关的新Product。为什么有in: context?因为当我省略它们时保存不执行。我收到了警告:NO CHANGES IN ** saveWithBlock:completion: ** CONTEXT - NOT SAVING

直到现在一切似乎还可以。 CoreDataEditor显示了这样的结构 CoreDataStructure

现在让我们继续删除操作。

尝试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个对象,忽略了我刚删除一个的事实。什么是更多的应用程序崩溃,因为收到的条目(一个应该被删除)没有相关的ProductCoreDataEditor仅显示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

1 个答案:

答案 0 :(得分:0)

MagicalRecord.save正在将数据保存到defaultContext

MagicalRecord.save({ (context) in
         _ = data(context)
     }) { (success, error) in
         completion(success,error)
     }

,而self.localContextmr_rootsaving ??

快速建议:

  1. 使用MagicalRecord.setupCoreDataStack(withAutoMigratingSqliteStoreNamed: dataStack)代替MagicalRecord.setupCoreDataStack(withStoreNamed: dataStack)。始终让MagicalRecord为您处理autoMigration。

  2. 在大多数情况下,我习惯使用MagicalRecord始终坚持使用defaultContext。对于您的用例,如果您始终使用self.localContext(将数据保存到MagicalRecord.save)保存数据,则您实际上无需明确创建defaultContext。然后,您只需使用let cart: Cart? = Cart.mr_findFirst()随时随地检索所需的数据。

  3. 更新回答

    感谢您更新@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)
    }
    

    说实话,基本上addfetch操作一切正常吗?剩下的问题是deletion。首先,尝试2 是我上面提到的上下文问题。

    所以让我们专注于

      

    效果1:完成块返回成功= true,错误= nil在此操作之后我们正在使用cart:cart刷新购物车? = Cart.mr_findFirst() - cart.entries字段有2个CartEntry对象,忽略了我刚删除的事实。什么是更多的应用程序崩溃,因为收到的条目(一个应该被删除)没有相关的产品。 CoreDataEditor仅显示1个条目。重新启动应用程序后,购物车再次正确 - 只有1个条目,没有我刚刚删除的数据。

    1. delete来电似乎没问题

    2. 应用程序崩溃是您实际删除条目的一个好兆头

    3. 您重新启动了该应用,只剩下一个条目,证明您的 删除声明完成了它的工作

    4. (您是否使用CoreDataEditor仔细检查结果?)

      所以我们可以确认所有其他部分都正常工作,唯一的问题似乎是您没有正确处理数据源更改。你使用的是UITableView吗?您是否使用NSFetchedResultsControllerDelegate扩展了课程并实施了委托方法?

      请告诉我们该部分的代码。 (用于显示数据的ViewController)。