3

I'm attempting to implement a KVC equivalent is Swift (inspired by David Owens) using reflection.

valueForKey is fairly trivial, using reflection to get all the children names and retrieve the appropriate value. setValueForKey has proved to be quite tricky however, as Swift reflection appears to be read-only (since readwrite would break reflections dogma)

protocol KVC {
    var codeables: [String: Any.Type] { get }
    mutating func setValue<T>(value: T, forKey key: String)
    func getValue<T>(key: String) -> T?
}


extension KVC {
    var codeables: [String: Any.Type] {
        var dictionary: [String: Any.Type] = [:]
        let mirror = Mirror(reflecting: self)
        for child in mirror.children {
            if let label = child.label {
                 dictionary[label] = Mirror(reflecting: child.value).subjectType
             }
         }
        return dictionary
    }

    mutating func setValue<T>(value: T, forKey key: String) {
        if let valueType = self.codeables[key] where valueType == value.dynamicType {

        }
    }

    func getValue<T>(key: String) -> T? {
        let mirror = Mirror(reflecting: self)
        for child in mirror.children {
            if let label = child.label, value = child.value as? T where label == key {
                return value
            }
        }
        return nil
    }
}

Is there anyway in Swift at all to set a dynamic keypath value without using the Objective-C runtime or enforcing that the conformer is a subclass of NSObject? It seems like the answer is no but there are some clever workarounds such as ObjectMapper, although I'm not a fan of the responsibility its on the conformer.

barndog
  • 6,975
  • 8
  • 53
  • 105
  • Swifts reflection is 100% read-only, so the answer is no, you'll have to use some nasty workaround (btw reflection is super slow) – Kametrixom Oct 29 '15 at 21:46
  • Is there a better way than reflection, something not as slow? And it seems as far as KVC goes is to either use 1) objc-runtime or 2) impose some client protocol on the conformer as ObjectMapper does – barndog Oct 29 '15 at 23:49
  • I use NSObject as the base type of the classes in https://github.com/evermeer/EVReflection I'm sure there is no other way for setting values for a key. In most cases the speed of reflection is good enough. In your case you do a Mirror in your getValue function. Then it will execute each time you want to get a value. If you want to access multiple values, then you should also create a getValuesDictionary so that you can get the data from there. – Edwin Vermeer Nov 05 '15 at 07:30

0 Answers0