天天看點

【iOS開發】@objc private class func 與 Selector

本文介紹在 Swift 中 使用 KVO 時,一些需要注意的事項,下面截取了兩段我自己在項目中使用的代碼。

self.timer = NSTimer.scheduledTimerWithTimeInterval(timeInterval, target: self,
        selector: "moveText", userInfo: nil, repeats: true)

NSNotificationCenter.defaultCenter().addObserver(self,
        selector: "appEnterForeground", name: nil, object: nil)
           

第一個是第一個定時器(NSTimer),第二個是一個頁面的監聽事件。即,讓程式不斷地觀察現在的『某個狀态』,當這個狀态符合某個條件時,就去執行 Selector 中的代碼。比如,我們的界面中有一個讓使用者輸入年齡的 UITextField,然後我們可以觀察(監聽),當發現使用者在這裡輸入『0』時,我們就給一個提示:『年齡至少為1』。

簡單介紹完畢,下面說注意事項。

<h3>1. private 關鍵字</h3>

最簡單的使用 Selector 的情況,就是如上面所列出的,在 NSTimer 中寫 selector 為 "moveText",然後我們在同一個檔案中,再相應地寫一個

func moveText(){ 
    // Your Code
}
           

就可以了。

然而如果你想把它聲明為一個 private func,即不希望其他檔案調用這個函數,就會出現問題,通俗地講:private 使得這個函數不能被『外部』調用,而 Selector 對它的調用,實際上就是一種『外部調用』。

【解決方案】

KVO 是基于 KVC 和動态派發技術(Dynamic Dispatch)的,Swift 為了效率禁用了 Objective-C 中有的動态派發。那麼你把這個動态特性再加回來就可以了~

1.通過 @objc 關鍵字來使用動态特性

@objc private func moveText(){ 
    // Your Code
}
           

2.通過 dynamic 關鍵字來讓這個函數擁有與 OC 中動态調用時相同的運作時特性(@objc 足矣,這個一般用不上)

dynamic private func moveText(){ 
    // Your Code
}
           

更多關于 dynamic 關鍵字的内容可以參考:

http://swifter.tips/kvo/

<h3>2. class 關鍵字</h3>

如果你想把這個函數聲明為 class func

class func moveText(){ 
    // Your Code
}
           

則本文最開始的代碼中的 target 應該由 self 換為 MyClass.self (假設這段代碼寫在名為 MyClass 的類中)

self.timer = NSTimer.scheduledTimerWithTimeInterval(timeInterval, target: MyClass.self,
        selector: "moveText", userInfo: nil, repeats: true)
           

最後, 以上關鍵字是可以疊加使用的,如果你願意,可以寫成下面這樣:

@objc private class func moveText(){ 
    // Your Code
}
           

我在 StackOverFlow 中的回答,及其它相關:

http://stackoverflow.com/questions/30027322/how-to-call-private-class-function-from-selector-in-swift/34291667#34291667 http://stackoverflow.com/questions/28184350/4-questions-about-selectors-in-swift

如有謬誤,歡迎在評論中指出。