天天看點

@objc關鍵字

前言:為了擺脫Objective-C沉重的曆史包袱,Apple于2014年6月發表了新的程式設計語言 Swift。但是曆經20多年發展浮沉的巨人Objective-C早已深入到Cocoa架構的方方面面,無數的第三方庫是用 Objective-C 寫成的。想要一刀切直接跨到Swift的時代,即使蘋果再激進也不敢這麼貿貿然。是以直到現在Swift2.0釋出依然還是有許多為了相容Objective-C所做的妥協。

Apple允許我們在同一個項目中同時使用Swift和Objective-C進行開發,雖然本質上兩者所處的世界是完全不同的,但是Apple提供了聯通兩者的橋梁給我們。

但是想要在Objective-C中使用Swift代碼的話并沒有那麼簡單,如我們所知,Objective-C對象是基于運作時的,消息傳遞機制是在運作時才決定實際調用的具體實作。而Swift為了提高性能,如果沒有特殊需要的話,成員以及方法在編譯時就已經決定了。基于上述差別,如果我們在Objective-C代碼中使用Swift類型的時候,會因為在運作時找不到所需要的資訊而導緻失敗。

解決這個問題,我們需要在Swift類型檔案中将暴露給 Objective-C 使用的任何地方 (包括類,屬性和方法等) 的聲明前面加上 @objc 修飾符。當你定義了一個繼承自NSObject或者其他 Objective-C 類的 Swift 類,這些類都能與 Objective-C 無縫連接配接。所有的步驟都有 Swift 編譯器自動完成,如果你從未在 Objective-C 代碼中導入 Swift 類,你也不需要擔心類型适配問題。換句話說隻要是NSObject以及其子類都可以不用手動添加@objc關鍵字即可在Objective-C中使用。

@objc關鍵字的另一個作用是為純Swift代碼在Objective-C中使用時提供一個别名。當你在 Objective-C 中使用 Swift API,編譯器基本對語句做直接的翻譯。例如,Swift 中的 func playSong(name: String)會被解釋為- (void)playSong:(NSString *)name。但是如果你不滿意這個自動翻譯的名字,又或者你的Swift代碼中包含了Objective-C不支援的字元,此時可以為Objective-C提供一個替代的名字。示例如下:

@objc(Color)
enum Цвет: Int {
    @objc(Red)
    case Красный

    @objc(Black)
    case Черный
}

@objc(Squirrel)
class Белка: NSObject {
    @objc(color)
    var цвет: Цвет = .Красный

    @objc(initWithName:)
    init (имя: String) {
        // ...
    }
    @objc(hideNuts:inTree:)
    func прячьОрехи(количество: Int, вДереве дерево: Дерево) {
        // ...
    }
}
           

你可以在類、屬性、方法、枚舉前加 “@objc(name)” 關鍵字來提供在Objective-C中的别名。