swift4 kvc

d_d發表於2018-10-29

問題

swift4中使用kvc:

class Person: NSObject {
    var dog: Dog?
}
class Dog: NSObject {
    var name: String
    init(name: String) {
        self.name = name
    }
}

let whiteDog = Dog(name: "white")
let person = Person()
person.setValue(whiteDog, forKey: "dog")
let myDog: Dog = person.value(forKeyPath: "dog") as! Dog
print(myDog.name)
複製程式碼

然後會發生crash得到如下資訊:

Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<RXLearn.Person 0x1c4002610> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key dog.'
複製程式碼

原因

swift為了效能優化,需要標記為@objc的屬性才能使用kvc,所以這樣:

class Person: NSObject {
    @objc var dog: Dog?
}
複製程式碼

swift4 新功能

無論結構體還是類都可以使用這個方法[keyPath: ReferenceWritableKeyPath<Root, Value>]進行取賦值。

class Person {
    var dog: Dog
    init(dog: Dog) {
        self.dog = dog
    }
}
class Dog {
    var name: String
    init(name: String) {
        self.name = name
    }
}
//
let blackDog = Dog(name: "black")
let whiteDog = Dog(name: "white")
let person = Person(dog: blackDog)
person[keyPath: \Person.dog] = whiteDog
        
let mydog = person[keyPath: name]
print(mydog.name) // 列印white
複製程式碼

person改為結構體依然可以:

struct Person {
    var dog: Dog
    init(dog: Dog) {
        self.dog = dog
    }
}
複製程式碼