這幾天在寫 Swift 4 的時候,一如往常的在處理 Keyboard 的 show/hide 問題。
結果偉大的 Xcode 9 跳出了警告
Argument of ‘#selector’ refers to instance method ‘keyboardWillShow’ that is not exposed to Objective-C
Add ‘@objc’ to expose this instance method to Objective-C
這段英文的意思我就不翻譯了,但總結是說要在 func 前面加 @objc 如下
我才驚覺,Target Action 是 Objective C 的 Design Pattern。(早該發現了,之前都混什麼吃的)
在 Swift 的 Virtual Table 設計的像是 Array 一樣,所以在取 func 的時候是使用 index 來取。
在 Objective C 的 Virtual Table 則是像 Dictionary 一樣,取 func 是把 selector 的名稱當成 key 去查表。
也就是說在不考慮其他條件下,Swift 取 func 的速度是比 Objective C 還快的。
我想要 Pure Swift 的寫法,想說 Swift 是否有其他的 Pattern 來做到一樣的功能。
詢問了 zonble ,得知純 Swift 沒有 Selector,要用 Selector 就一定會透過 @objc 來跟 Objective C 做 Bridge。
慶幸的是 AddObserver 有出 Block 版本( Swift 稱為 Closure)
將程式碼改為以下
因為這是個跟畫面有關係的行為,所以要到 Main queue 處理。
常用的 Targer Action 還有 NSTimer (Swift 稱 Timer),我之前也有用Accelerometer(加速儀)也可以使用 Block,這樣可以在 Swift 裡面減少使用 objc 這個歷史的包袱。
不過目前仍然有遇到沒有辦法透過 block 來處理的情況,如 Gesture。寫法還是只能像以下那樣。
如果有人知道 Gesture 怎麼寫可以讓 Swift 更 Pure 的話,還請務必指點一下。
註:我今天才知道原來有 Pure Swift 這種說法,好像就是盡量少跟 Objc 扯上關係的寫法。
註2:keyboard show/hide 的實作這邊是省略的。