如何让 NSBatchDeleteRequest 删除并允许您再次添加回对象

Posted

技术标签:

【中文标题】如何让 NSBatchDeleteRequest 删除并允许您再次添加回对象【英文标题】:How to get a NSBatchDeleteRequest to delete and allow you to add back to an object again 【发布时间】:2016-11-12 23:08:53 【问题描述】:

我有以下代码。

let workorderFetchRequest   = NSFetchRequest<NSFetchRequestResult>(entityName: "Workorders")
                let deleteWorkOrderRequest  = NSBatchDeleteRequest(fetchRequest: workorderFetchRequest) //Deletes ALL workorders

                //Question is will it delete all references to the work orders correctly now?
                try context.execute(deleteWorkOrderRequest)

                //Save the work order objects (overwriting any old ones with same id if needed)
                do 
                    try context.save()
                    print("Saved context with workorders")
                 catch let error as NSError  
                    print("Could not save \(error), \(error.userInfo)")
                 catch 
                    print("Could not save, unknown error")
                

                print("deleted references")

工单看起来像这样...

import Foundation
import CoreData

extension Workorders 

    @nonobjc public class func fetchRequest() -> NSFetchRequest<Workorders> 
        return NSFetchRequest<Workorders>(entityName: "Workorders");
    

    @NSManaged public var address: String?
    @NSManaged public var client_id: Int64
    @NSManaged public var desc: String?
    @NSManaged public var id: Int64
    @NSManaged public var phone: String?
    @NSManaged public var signaturepath: String?
    @NSManaged public var lat: String?
    @NSManaged public var lng: String?
    @NSManaged public var service: Service?
    @NSManaged public var pictures: NSSet?
    @NSManaged public var videos: NSSet?



// MARK: Generated accessors for pictures
extension Workorders 

    @objc(addPicturesObject:)
    @NSManaged public func addToPictures(_ value: Pictures)

    @objc(removePicturesObject:)
    @NSManaged public func removeFromPictures(_ value: Pictures)

    @objc(addPictures:)
    @NSManaged public func addToPictures(_ values: NSSet)

    @objc(removePictures:)
    @NSManaged public func removeFromPictures(_ values: NSSet)



// MARK: Generated accessors for videos
extension Workorders 

    @objc(addVideosObject:)
    @NSManaged public func addToVideos(_ value: Videos)

    @objc(removeVideosObject:)
    @NSManaged public func removeFromVideos(_ value: Videos)

    @objc(addVideos:)
    @NSManaged public func addToVideos(_ values: NSSet)

    @objc(removeVideos:)
    @NSManaged public func removeFromVideos(_ values: NSSet)


我让它引用了一个看起来像这样的服务对象......

import Foundation
import CoreData

extension Service 

    @nonobjc public class func fetchRequest() -> NSFetchRequest<Service> 
        return NSFetchRequest<Service>(entityName: "Service");
    

    @NSManaged public var id: Int64
    @NSManaged public var name: String?
    @NSManaged public var templatedata: String?
    @NSManaged public var workorder: Workorders?


当我在工作订单模型上运行删除代码时,它设置为 作为删除规则无效 ...(请参阅下图)

当我运行批量删除时,它似乎并没有正确地取消服务。当我尝试在工作订单上设置新服务时,它会崩溃...

libc++abi.dylib:以 NSException 类型的未捕获异常终止

我确定是这种情况,因为如果我将删除规则设置为级联工作订单,那么它可以解决问题。但是,我想保留旧服务只是取消引用。

为什么我不能在工作订单上设置新服务而不会崩溃?

下面是代码中的区域,它通过查看控制台消息而崩溃,我已将其范围缩小到我尝试设置服务的那一刻。

另外请注意,我使用的是 NSMergeByPropertyObjectTrumpMergePolicy,因为我打算再次为工作订单设置相同的 ID 服务,因此当我创建具有相同 ID 的新服务时,它应该只覆盖数据如果我的理解是正确的,旧的服务。这可能是问题所在,如果是,我该如何解决?

【问题讨论】:

【参考方案1】:

我在您的尝试中发现了一些问题。

首先,我认为您需要修改实体名称。它们应该是单一类型。

例如,您为它们使用了“工作订单”或“图片”。 应该是“工单”和“图片”。

主要问题是您在设置正确的关系之前同步了 managedObjects。

例如,您创建了一个服务对象,它的工作订单关系还为零。 在这一点上,您保存了上下文。 如果您有可选的关系,则可能会发生这种情况。

您创建了工作订单对象并将现有服务绑定到它的关系。

Core Data 尝试将新的工作订单绑定到服务对象的工作订单关系,反之亦然。

所以它应该在一个事务中完成。 最后,这意味着您需要在完成建立关系后保存一次上下文。

因此删除服务的 saveContext 行。

假设您像现在一样做到了。 使用新服务保存上下文后,您创建了 workorder1,并为其关系设置了服务。然后应用程序崩溃或被某些东西停止。 在这些情况下,它会导致数据完整性问题。

我希望这将有助于您了解这个问题并解决它。

干杯!

【讨论】:

【参考方案2】:

好吧,我意外地找到了我的问题的答案。

似乎您不必提前保存上下文以便一个对象被另一个对象引用,实际上......您不应该!

这样做显然会使 nsbatchdelete 不同步。我不确定如何解决这个问题,并且会感谢比我自己更好的答案。

总之我摆脱了早...

do 
                    try context.save()
                    print("Saved context with workorders")
                 catch let error as NSError  
                    print("Could not save \(error), \(error.userInfo)")
                 catch 
                    print("Could not save, unknown error")
                

在我保存服务之后,因为它显然是不必要且有害的。

这确实引出了一个问题,如果我要在此之后进行另一个事务,我需要保存上下文并删除,这个错误会再次发生吗?

【讨论】:

以上是关于如何让 NSBatchDeleteRequest 删除并允许您再次添加回对象的主要内容,如果未能解决你的问题,请参考以下文章

使用带有 NSBatchDeleteRequest 的 NSFetchedResultsController

UI 在执行 NSBatchDeleteRequest 时冻结

NSBatchDeleteRequest 留下不好的关系

在 NSBatchDeleteRequest 之后使用核心数据

核心数据 NSBatchDeleteRequest 似乎将对象留在上下文中

如何让Markdown图片居中