1. 程式人生 > >Swift - Swift4新特性介紹1(Key Paths新語法、類與協議的組合型別)

Swift - Swift4新特性介紹1(Key Paths新語法、類與協議的組合型別)

原文 http://www.hangge.com/blog/cache/detail_1823.html

文章目錄

Key Paths 新語法

key-path 通常是用在鍵值編碼(KVC)與鍵值觀察(KVO)上的。

歷史版本

Swift3 之前使用的是 String 型別的 key-Path

//使用者類
class
User: NSObject{ @objc var name:String = "" //姓名 @objc var age:Int = 0 //年齡 } //建立一個User例項物件 let user1 = User() user1.name = "hangge" user1.age = 100 //使用KVC取值 let name = user1.value(forKey: "name") print(name) //使用KVC賦值 user1.setValue("hangge.com", forKey: "name")

到了Swift3新增了 #keyPath() 寫法

//使用者類
class User: NSObject{ @objc var name:String = "" //姓名 @objc var age:Int = 0 //年齡 } //建立一個User例項物件 let user1 = User() user1.name = "hangge" user1.age = 100 //使用KVC取值 let name = user1.value(forKeyPath: #keyPath(User.name)) print(name) //使用KVC賦值 user1.setValue("hangge.com", forKeyPath: #keyPath(User
.name))

swift 4 中直接用 \ 作為開頭建立 KeyPath

新的方式不僅使用更加簡單,而且有如下優點:
型別可以定義為 class、struct
定義型別時無需加上 @objc 等關鍵字
效能更好
型別安全和型別推斷,例如:user1.value(forKeyPath: #keyPath(User.name)) 返回的型別是 Any,user1[keyPath: \User.name] 直接返回 String 型別
可以在所有值型別上使用

  1. 比如上面的樣例在 Swift4 中可以這麼寫:
//使用者類
class User: NSObject{
    var name:String = ""  //姓名
    var age:Int = 0  //年齡
}
 
//建立一個User例項物件
let user1 = User()
user1.name = "hangge"
user1.age = 100
 
//使用KVC取值
let name = user1[keyPath: \User.name]
print(name)
 
//使用KVC賦值
user1[keyPath: \User.name] = "hangge.com"
  1. keyPath 定義在外面也是可以的:
let keyPath = \User.name
 
let name = user1[keyPath: keyPath]
print(name)
 
user1[keyPath: keyPath] = "hangge.com"
  1. 可以使用 appending 方法向已定義的 Key Path 基礎上填加新的 Key Path。
let keyPath1 = \User.phone
let keyPath2 = keyPath1.appending(path: \.number)

類與協議的組合型別

在 Swift4 中,可以把類(Class)和協議(Protocol)用 & 組合在一起作為一個型別使用。

使用樣例1:

protocol MyProtocol { }
 
class View { }
 
class ViewSubclass: View, MyProtocol { }
 
class MyClass {
    var delegate: (View & MyProtocol)?
}
 
let myClass = MyClass()
myClass.delegate = ViewSubclass() //這個編譯正常
myClass.delegate = View() //這個編譯報錯:

使用樣例2:

protocol Shakeable {
    func shake()
}
 
extension UIButton: Shakeable {
    func shake() {
        /* ... */
    }
}
 
extension UISlider: Shakeable {
    func shake() {
        /* ... */
    }
}
 
func shakeEm(controls: [UIControl & Shakeable]) {
    for control in controls where control.isEnabled {
        control.shake()
    }
}