iosswiftcore-datakey-value-coding

update key values of NSManagedObjects safely


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...


Solution

  • 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.