update key values of NSManagedObjects safely

456 Views Asked by At

I'm trying to pass key value pairs and have the attributes updated through a loop.

func update(storableClass : NSManagedObject.Type, id: ID, fields: [String : Any]) throws {

    // retreive manaagedObject
    for (key, value) in fields {
        manaagedObject.setValue(value, forKey: key)
    }
}

Apparently the setValue(_:forKey:) will throw an exception if the key doesn't exist.

From what I've learned you're not to catch an Objective-C exception in Swift.

Is there any safe way to update core data properties through a dictionary?

I know I can have a function like below:

func update(storableClass : ManagedObject.Type, id: ID, closure: (ManagedObject) -> ()) throws {}

and then call it as such:

update(storableClass: UserEntity.self, id: "123123", closure: { userEntity in
    userEntity.name = "new name" 
})

I like to have both options...and any other safe/swifty option...

1

There are 1 best solutions below

2
Tom Harrington On BEST ANSWER

I've had this exact problem. Here's what you do.

With Core Data, you can easily find out what property names are valid for the object. Get a reference to the managed object's entity, and then ask the entity for the properties. You'd use managedObject.entity.propertiesByName. The result is a dictionary where the keys are valid properties. The code would be something like

let properties = managedObject.entity.propertiesByName
for (key, value) in fields {
    if properties[key] != nil {
        managedObject.setValue(value, forKey: key)
    } else {
        print("Unknown key: \(key)")
    }
}

This is fine as long as value is the right type. If you start getting bogus data types in JSON, you have a more complex problem to solve.

For relationships, do the same thing with managedObject.entity.relationshpsByName.