1
votes

I have an entity in CoreData which has an optional property of type Integer 16. It can genuinely be nil and in my application I want to refer to it as an Int? type. As Int? (or for that matter Int16?) isn't a recognised Objective-C type, the compiler throws a bit of a wobbly. I want to avoid using code like NSNumber?.intValue throughout so I've actually set up my ManagedObject type with custom accessors for this property. My question relates to identifying the property through #keyPath rather than a static string. In Core Data the field is named 'pin' on entity 'User'. Here's the code I have:

class User: NSManagedObject {
// MARK: - Properties
static let pinKey = "pin"

@NSManaged internal(set) var name: String
@NSManaged fileprivate var primitivePin: NSNumber?

internal(set) var pin: Int? {
    get {
        willAccessValue(forKey: #keyPath(pin))  // THIS LINE ERRORS
        let value: Int? = primitivePin.map { $0.intValue }
        didAccessValue(forKey: User.pinKey)
        return value
    }
    set {
        willChangeValue(forKey: User.pinKey)
        primitivePin = newValue.map { NSNumber(value: Int16($0)) }
        didChangeValue(forKey: User.pinKey)
    }
}

}

The line in error is what I 'want' to achieve but of course the var pin isn't an obj-c type and the compiler complains, so I have defined the static constant pinKey as you can see. #keyPath feels like the right way to go about it, and the entity does have a field called pin, but in this scenario is the only option open to me to use a static value?

2

2 Answers

2
votes

In #keyPath you have to specify property name. If you don't have defined property called pin, you will receive an error. In your case you have to use #keyPath(User.primitivePin). I believe this should work.

Also, i guess, calling map is redundant here. You can write directly let value = primitivePin?.intValue and so on.

0
votes

The answer is....with custom properties/accessors #keyPath can't used as there is no defined @NSManaged property for it - as Maksym points out. However, you can't use the defined primitive for it either, instead using the property name as a String as also shown in the code above (User.pinKey)