Pure Swift 之 Target Action 處理

這幾天在寫 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 的實作這邊是省略的。