首页 > 解决方案 > 如何使用 swift 4.2 学习 KVC

问题描述

我正在使用带有 swift 4.2 的 Xcode 10.0 从“Cocoa Programming for OSX”中了解键值编码

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

import Cocoa

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

let student1 = Student()


student1.setValue("Benny", forKeyPath: "name")

student1.setValue("Benny", forKeyPath: "name")

生成以下错误消息:

执行被中断,原因:EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)。

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

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

标签: swiftkvc

解决方案


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

@objc var name: String = ""

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

  1. #keyPath指令也使用 ObjC 运行时,但在编译时检查密钥路径

    let keyPath = #keyPath(Student.name)
    student1.setValue("Benny", forKeyPath: keyPath)
    

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

    '#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"
    

推荐阅读