如何使用Swift 4.2了解KVC

hob*_*Bob 4 kvc swift

我正在使用带有Swift 4.2的Xcode 10.0,以从“用于OSX的可可编程”中了解键值编码

我被要求创建一个简单的类,它是NSObject的子类。以下代码:

import Cocoa

class Student: NSObject {
    var name: String = ""
    var gradeLevel: Int = 0
}

let student1 = Student()


student1.setValue("Benny", forKeyPath: "name")
Run Code Online (Sandbox Code Playgroud)

student1.setValue(“ Benny”,forKeyPath:“名称”)

生成以下错误消息:

执行被中断,原因:EXC_BAD_INSTRUCTION(代码= EXC_I386_INVOP,子代码= 0x0)。

我在网上看过,似乎有些关于KVC的问题,例如:https : //bugs.swift.org/browse/SR-5139

我究竟做错了什么?该书于2015年出版。

vad*_*ian 6

在Swift 4中,出于性能原因,不再推断将代码公开给Objective-C运行时。
为了避免崩溃,您必须@objc显式添加属性。

@objc var name: String = ""
Run Code Online (Sandbox Code Playgroud)

但是从Swift的强类型角度来看,有两种更好的方法来使用KVC获取值:

  1. #keyPath它使用ObjC运行时,过指令,但检查在编译时的关键路径

    let keyPath = #keyPath(Student.name)
    student1.setValue("Benny", forKeyPath: keyPath)
    
    Run Code Online (Sandbox Code Playgroud)

    在这种情况下,您会得到非常有描述性的编译器警告

    “ #keyPath”的参数引用“ Student”中的属性“ name”,该属性取决于Swift 4中弃用的“ @objc”推论

  2. (推荐的)本地方式:Swift 4+提供了自己的KVC模式,NSObject不需要子类化。
    关键路径由反斜杠开头,后跟类型和属性(或多个属性):

    class Student {
        var name: String = ""
        var gradeLevel: Int = 0
    }
    
    let student1 = Student()
    student1[keyPath: \Student.name] = "Benny"
    
    Run Code Online (Sandbox Code Playgroud)