Search code examples
ioscore-datansmanagedobjectnsmanagedobjectcontextmagicalrecord

CoreData occurred error on device but fine on simulator


I just tried using core data to do something, my goal is create a object with a child context, assign the values for an object, and then save it to storage after doing some operations.

It works fine on simulator, but an error occurred when running on a device.

This is the error :

CoreData: error: Mutating a managed object 0x174033540 (0x1740cb600) after it has been removed from its context.

my code :

Extestion

extension NSManagedObject {
    class func GV_New() -> NSManagedObject {
        let entity = self.MR_entityDescription();
        let parentContext = NSManagedObjectContext.MR_defaultContext();
        let childContext = NSManagedObjectContext.MR_contextWithParent(parentContext);

        let managedObject = NSManagedObject(entity: entity, insertIntoManagedObjectContext: childContext);

        return managedObject;
    }

    class func GV_Insert(object: NSManagedObject) -> Bool {
        var result: Bool = false;

        let keyPath = "userInfo.primaryKey";
        let primaryKey = self.MR_entityDescription().valueForKeyPath(keyPath) as String!;

        if primaryKey != nil {
            if (self.MR_findFirstByAttribute(primaryKey, withValue: object.valueForKey(primaryKey)) != nil) {
                result = false;
            } else {
                let managedObjectId = object.objectID;
                let managedObjectContext = object.managedObjectContext;
                let managedObject = managedObjectContext!.existingObjectWithID(managedObjectId, error: nil);
                managedObject?.managedObjectContext?.MR_saveOnlySelfAndWait();
                NSManagedObjectContext.MR_defaultContext().MR_saveToPersistentStoreAndWait();

                result = true;
            }
        }
        return result;
    }
}

ViewController

class ViewController: UIViewController {
    var camera: Camera!;
    override func viewDidLoad() {
        super.viewDidLoad();

        println("\(Camera.MR_countOfEntities())");

        camera = Camera.GV_New() as Camera;
        camera.camera_id = 4567;
        Camera.GV_Insert(camera);

        println("\(Camera.MR_countOfEntities())");

        for (index, value) in enumerate(Camera.MR_findAll()) {
            let result = value as Camera;
            println("result: \(value.camera_id)");
        }
    }
}

Solution

  • just resolved this problem,

    I haven't retain the child context, since swift not supported class variables yet,

    just set managedContext on the file.

    let managedContext = NSManagedObjectContext.MR_context();

    let managedContext = NSManagedObjectContext.MR_context();
    
    extension NSManagedObject {
    
        class func GV_New() -> NSManagedObject {
    
            return self.MR_createInContext(managedContext) as NSManagedObject;
    
        }
    
        class func GV_Insert(object: NSManagedObject) -> Bool {
    
            var result: Bool = false;
    
            let keyPath = "userInfo.primaryKey";
    
            let primaryKey = self.MR_entityDescription().valueForKeyPath(keyPath) as String!;
    
            if primaryKey != nil {
    
                if (self.MR_findFirstByAttribute(primaryKey, withValue: object.valueForKey(primaryKey)) != nil) {
    
                    result = false;
    
                }
    
                else {
    
                    object.managedObjectContext?.MR_saveOnlySelfAndWait();
    
                    NSManagedObjectContext.MR_defaultContext().MR_saveToPersistentStoreAndWait();
    
                    result = true;
    
                }
    
            }
    
            return result;
    
        }
    
    }