Swift 4:KeyPath

Swift 4对KeyPath做了很大的改进。改进后的为类型安全的KeyPath。

Swift 2的KeyPath

示例

class Person: NSObject {
  var name: String = ""

  init(name: String) {
    self.name = name
  }
}
let me = Person(name: "张三")
me.valueForKeyPath("name")

Swift 2的KeyPath为一个字符串。显然,使用字符串作为KeyPath很容易造成拼写错误。

Swift 3的KeyPath

鉴于使用字符串作为keypath的值很容易造成拼写错误,Swift 3新增了#keyPath()来增强KeyPath的类型安全。

class Person: NSObject {
  var name: String = ""

  init(name: String) {
    self.name = name
  }
}
let me = Person(name: "张三")
me.value(forKeyPath: #keyPath(Person.name))

Swift 4新的KeyPath

虽然Swift 3新增了#keyPath()来对KeyPath做类型检查,但是检查后返回的仍然是字符串。

Swift 3的KeyPath有以下几个缺点

  • 丢失了类型信息(因为#keyPath()返回的仍然是字符串,做KeyPath的所有类型都是Any)
  • 需要对#keyPath()检查后返回的字符串做没必要的解析
  • KeyPath只能应用于NSObject
  • 局限于Darwin平台

Swift 4新引入了反斜杠"\"来表示KeyPath,其语法为:

  • \<Type>.<path>
  • \.<path>

<Type>:类型名
<path>:由一个或以上的属性构成的路径链,即property.property.....

如果可以推断出KeyPath对应的类型可以使用点号"\."开头,省略类型名。

Smart KeyPaths: Better Key-Value Coding for Swift的示例

class Person {
    var name: String
    var friends: [Person] = []
    var bestFriend: Person? = nil
    init(name: String) {
        self.name = name
    }
}

var han = Person(name: "Han Solo")
var luke = Person(name: "Luke Skywalker")
luke.friends.append(han)

简单的KeyPath:Person.name

let hanName = han[keyPath:\.name]  //Han Solo

取得数组的KeyPath

let firstFriendsNameKeyPath = \Person.friends[0].name
let firstFriend = luke[keyPath: firstFriendsNameKeyPath] // "Han Solo"
// 等同于
luke[keyPath: \.friends[0].name] // "Han Solo"
//等同于
luke.friends[keyPath: \.[0].name] // "Han Solo"
//等同于
luke.friends[keyPath: \[Person].[0].name] // "Han Solo"

使用KeyPath修改属性值

// rename Luke's first friend
luke[keyPath: firstFriendsNameKeyPath] = "A Disreputable Smuggler"

可选属性的KeyPath

// optional properties work too
let bestFriendsNameKeyPath = \Person.bestFriend?.name
let bestFriendsName = luke[keyPath: bestFriendsNameKeyPath]  // nil, if he is the last Jedi

参考:https://github.com/apple/swift-evolution/blob/master/proposals/0161-key-paths.md

版权声明:著作权归作者所有。

相关推荐

Swift 4 Codable协议 - 基本用法

Swift 4新增了Codable协议,它是一个组合协议,包含Encodable和Decodable两个协议。代码定义如下:/// A type that can convert itself into and out of an external repre

Swift 4的KVO(Key Value Observation)用法

KVO 是 Objective-C 对观察者模式的实现。当被观察对象的某个属性发生更改时,观察者对象会获得通知。KVO实现依赖于Objective-C的Runtime,所以Swift需要使用@objc暴露api给Objective C。Swift目前没有内置原生实现的值观察系统,Swift 4的KVO使用dynamic属性来实现。被观察的类clas

Swift日期和字符串互相转换(Swift 3/Swift 4)

Swift随着版本的升级,日期类都会有一点变化。所以各个版本的Swift日期和字符串的转换有所不同。Swift 4String转换为Datevar dateString = "2017-11-17" var dateFormatter = DateFormatter() // dateFormat

使用Swift 3/Swift 4扫描二维码

iOS的AVFoundation内置了对二维码和条形码扫描的支持。使用AVFoundation扫描二维码的功能需要几件事:创建AVCaptureSession,用于捕获二维码创建预览捕获二维码成功后,委派回调来处理二维码的meta信息下面的例子是基于UIViewController开发的扫描二维码Controller,使用AVCaptureMetadataOutputObjectsDelegate

Swift3/Swift4 转换Html为纯文本

Swift 3或者Swift 4 添加String扩展,把Html字符串转换为纯文本Xcode 9 beta • Swift 4extension String {     var html2AttributedString: NSAttr