Swift (與Objective C的相容問題)

2021-09-19 11:08:55 字數 1986 閱讀 7472

雖然說 swift 語言的初衷是希望能擺脫 objective-c 的沉重的歷史包袱和約束,但是不可否認的是經過了二十多年的洗禮,cocoa 框架早就烙上了不可磨滅的 objective-c 的印記。無數的第三方庫是用 objective-c 寫成的,這些積累無論是誰都不能小覷。因此,在最初的版本中,swift 不得不考慮與 objective-c 的相容。

首先通過新增 -bridging-header.h 檔案,並在其中填寫想要使用的頭檔名稱,我們就可以很容易地在 swift 中使用 objective-c **了。xcode 為了簡化這個設定,甚至在 swift 專案中第一次匯入 objective-c 檔案時會主動彈框進行詢問是否要自動建立這個檔案,可以說是非常方便。

但是如果想要在 objective-c 中使用 swift 的型別的時候,事情就複雜一些。如果是來自外部的框架,那麼這個框架與 objective-c 專案肯定不是處在同乙個 target 中的,我們需要對外部的 swift module 進行匯入。這個其實和使用 objective-c 的原來的 framework 是一樣的,對於乙個專案來說,外界框架是由 swift 寫的還是 objective-c 寫的,兩者並沒有太大區別。我們通過使用 2013 年新引入的 @import 來引入 module:

@import myswiftkit;
之後就可以正常使用這個 swift 寫的框架了。

但這只是故事的開始。objective-c 和 swift 在底層使用的是兩套完全不同的機制,cocoa 中的 objective-c 物件是基於執行時的,它從骨子裡遵循了 kvc (key-value coding,通過類似字典的方式儲存物件資訊) 以及動態派發 (dynamic dispatch,在執行呼叫時再決定實際呼叫的具體實現)。而 swift 為了追求效能,如果沒有特殊需要的話,是不會在執行時再來決定這些的。也就是說,swift 型別的成員或者方法在編譯時就已經決定,而執行時便不再需要經過一次查詢,而可以直接使用。

顯而易見,這帶來的問題是如果我們要使用 objective-c 的**或者特性來呼叫純 swift 的型別時候,我們會因為找不到所需要的這些執行時資訊,而導致失敗。解決起來也很簡單,在 swift 型別檔案中,我們可以將需要暴露給 objective-c 使用的任何地方 (包括類,屬性和方法等) 的宣告前面加上 @objc 修飾符。注意這個步驟只需要對那些不是繼承自 nsobject 的型別進行,如果你用 swift 寫的 class 是繼承自 nsobject 的話,swift 會預設自動為所有的非 private 的類和成員加上 @objc。這就是說,對乙個 nsobject 的子類,你只需要匯入相應的標頭檔案就可以在 objective-c 裡使用這個類了。

@objc 修飾符的另乙個作用是為 objective-c 側重新宣告方法或者變數的名字。雖然絕大部分時候自動轉換的方法名已經足夠好用 (比如會將 swift 中類似 init(name: string) 的方法轉換成 -initwithname:(nsstring *)name 這樣),但是有時候我們還是期望 objective-c 裡使用和 swift 中不一樣的方法名或者類的名字,比如 swift 裡這樣的乙個類:

class 我的類   

}

我的類().打招呼("小明")

objective-c 的話是無法使用中文來進行呼叫的,因此我們必須使用 @objc 將其轉為 ascii 才能在 objective-c 裡訪問:

@objc(myclass)  

class 我的類

}

我們在 objective-c 裡就能呼叫 [[myclass new] greeting:@"xiaoming"] 這樣的**了 (雖然比起原來一點都不好玩了)。另外,正如上面所說的以及在 selector 一節中所提到的,即使是 nsobject 的子類,swift 也不會在被標記為 private 的方法或成員上自動加 @objc。如果我們需要使用這些內容的動態特性的話,我們需要手動給它們加上 @objc 修飾。

本文摘自王巍

objective學習筆記1

cocoa 是蘋果公司為 macos x 所建立的原生物件導向的 api,cocoa 是蘋果公司的物件導向的開發環境,該環境下的任何類都要繼承自 nsobject 只有這樣,該類的物件才可以獲得執行時的基本能力 cocoa 的主要開發語言是 objective c cocoa 包含兩個核心框架 fo...

把proto檔案編譯成objective c檔案

liliang的專欄 當前最新版本2.4.1 最後make install後,會生成編譯器protoc,並拷貝到 usr local bin目錄下。目前有兩種型別的實現。乙個針對protocolbuffer2.2做修改,使最後生成的.proto檔案編譯器 protoc 支援objective c型別...

swift與結構體

struct resolution 所有結構體都有乙個自動生成的成員逐一構造器,用於初始化新結構體例項中成員的屬性 let vga resolution width 640,height 480 let someresolution resolution println vga.width prin...