简体   繁体   中英

How to get a NSBatchDeleteRequest to delete and allow you to add back to an object again

I have the following code.

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")

A workorders looks like this...

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)

}

I have it referencing a service object that looks like this...

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?

}

When I run the delete code I have on the model for workorder it set to Nullify as the delete rule ... (refer to image below)

在此输入图像描述

When I run the batch delete however it does not seem to be nullifying service correctly. When I attempt to set a new service onto the workorder it crashes with...

libc++abi.dylib: terminating with uncaught exception of type NSException

I'm sure this is the case because if I set the delete rule to cascade on the workorders then it fixes the issue . However, I want to keep the old services just nullify the reference.

Why can I not set a new service onto the workorder without it crashing?

Attached below is the area in code it crashes by looking at the console messages I've narrowed it down to the moment I attempt to set service.

在此输入图像描述

Also note, I'm using a NSMergeByPropertyObjectTrumpMergePolicy since I intend to set the same ID service to the workorder again, so when I create a new service with the same ID it should just overwrite the data of the old service if my understanding is correct. Could this be the issue, and if so how do I fix it?

I find some issues from your trying.

At first, I think you need to revise Entity names. They should be single type.

For example, you used "Workorders" or "Pictures" for them. It should be "Workorder" and "Picture".

And the main issue is that you synced managedObjects before you setup right relationship.

For example, you created one service object and its workorder relationship is nil yet. In this point, you saved context. It could happen if you had optional relationship.

And you created workorder object and bind existing service to its relationship.

Core Data tries to bind new workorder to workorder relationship of service object vise versa.

So it should be done in one transaction. Finally it means you need to save context once after you complete setting up relationship.

So remove saveContext line for service.

Lets say you did it as you did now. After you save context with new service, you created workorder1 with setting service for its relationship. And then the app crashed or has been stopped by something. It causes data integrity issue in those cases.

I hope this will help your understanding about this issue and solved it.

Cheers!

Ok I surprisingly found the answer to my issue.

It appears you do not have to save the context early for an object to be referenced by another and in fact...you should not!

Doing this puts the nsbatchdelete out of sync apparently. I'm not sure how and would appreciate a better answer than my own for why this fixes it.

In short I got rid of the early...

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")
                }

after I saved the services as it was apparently unnecessary and harmful.

This does beg the question if I were to do another transaction after this where I need to save the context and delete will this error occur again?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM