Search code examples
swiftcore-databooleankvc

Swift: Boolean attributes and KVC mysteries


So I'm playing with this simple CoreData entity

import CoreData

class Figure: NSManagedObject {
    @NSManaged var approx: NSNumber? // Defined as Boolean type without default value
}

As you would expect, for a new figure, you get

figure.approx # nil
figure.valueForKey("approx") # nil

But, if you define the following (yes, I know, I could instead set a default value in the data model, that's not the point)

var isApprox: Bool {
  guard let approx = approx else { return false }
  return approx == true
}

Then suddenly

figure.valueForKey("approx") # false

Alright, so for some (to me) mysterious reason, it's actually relying on isApprox. I assumed that it is synthesized and I'm unknowingly overriding it, but if you remove the isApprox declaration and try to call it using KVC, it crashes:

figure.valueForKey("isApprox") # Execution was interrupted

Going further, if you have the following:

class Figure: NSManagedObject {
    @NSManaged var approx: NSNumber?

    var isApproximate: Bool {
      guard let approx = approx else { return false }
      return approx == true
    }
}

Now you get

figure.valueForKey("approx") # nil - expected
figure.valueForKey("isApproximate") # false - expected
figure.valueForKey("approximate") # false - where does this one come from?
figure.isApprox # error: value of type 'Figure' has no member 'isApprox'

I couldn't find any documentation about that, I'm curious to understand what's happening.


Solution

  • I think this article in the Key Value Coding Reference manual covers the behaviour you are noticing.

    Specifically, the section entitled "Default Search Pattern for valueForKey:" indicates that for a given key, the valueForKey: will try a range of different accessor methods, including both "key" and "isKey" (and interestingly, it will try "getKey" before either of them).