標籤:objc objective-c swift
今天隔壁老王突然問起我,Swift裡面的@objc是個神馬玩意兒?於是就有了今天的這個tip。那麼話說回來,既然說到@objc,就不得不扯一扯Swift和Objective-C之間不得不說的一些事啦^_^
Objective-C和Swift混合開發
Swift 語言的初衷是希望能擺脫 Objective-C 的沉重的曆史包袱和約束,但是不可否認的是經過了二十多年的洗禮,Cocoa 架構早就烙上了不可磨滅的 Objective-C 的印記。無數的第三方庫是用 Objective-C 寫成的,這些積累無論是誰都不能小覷。因此,在最初的版本中,Swift 不得不考慮與 Objective-C 的相容。
Apple 採取的做法是允許我們在同一個項目中同時使用 Swift 和 Objective-C 來進行開發。其實一個項目中的 Objective-C 檔案和 Swift 檔案是處於兩個不同世界中的,為了讓它們能相互聯通,我們需要添加一些橋樑。
當然這個橋樑檔案,在新的xcode版本中,是會自動提示是否需要產生,並幫大家自動產生的,所以不需要在意這個問題。
@objc的使用情境一:
Objective-C 和 Swift 在底層使用的是兩套完全不同的機制,Cocoa 中的 Objective-C 對象是基於運行時的,它從骨子裡遵循了 KVC (Key-Value Coding,通過類似字典的方式儲存物件資訊) 以及動態派發 (Dynamic Dispatch,在運行調用時再決定實際調用的具體實現)。而 Swift 為了追求效能,如果沒有特殊需要的話,是不會在運行時再來決定這些的。也就是說,Swift 類型的成員或者方法在編譯時間就已經決定,而運行時便不再需要經過一次尋找,而可以直接使用。
顯而易見,這就是@objc的一個使用情境之一,如果我們要使用 Objective-C 的代碼或者特性來調用純 Swift 的類型時候,我們會因為找不到所需要的這些運行時資訊,而導致失敗。
注意:
這個步驟只需要對那些不是繼承自 NSObject 的類型進行,如果你用 Swift 寫的 class 是繼承自 NSObject
的話,Swift 會預設自動為所有的非 private 的類和成員加上 @objc
。這就是說,對一個 NSObject 的子類,你只需要匯入相應的標頭檔就可以在 Objective-C 裡使用這個類了。
@objc的使用情境二:
雖然絕大部分時候自動轉換的方法名已經足夠好用 (比如會將 Swift 中類似 init(name: String) 的方法轉換成 -initWithName:(NSString *)name 這樣),但是有時候我們還是期望 Objective-C 裡使用和 Swift 中不一樣的方法名或者類的名字,比如 Swift 裡這樣的一個類:class Person{ func Hello(name: String) { println("Hello,\(name)") }}Person().Hello("小明")
可以通過@objc來進行修改
@objc(MyClass)class Person{ @objc(greeting:) func Hello(name: String) { println("Hello,\(name)") }}
然後我們就可以這樣進行Objective-C中的調用了:[[MyClass new] greeting:@"小明"]
最後做一個說明:
說明
添加 @objc 修飾符並不意味著這個方法或者屬性會變成動態派發,Swift 依然可能會將其最佳化為靜態調用。如果你需要和 Objective-C 裡動態調用時相同的運行時特性的話,你需要使用的修飾符是 dynamic。
Swift學習之每日一tip (7) @objc