本文主要閒聊一些 Objective-C 和 Swift 混編項目帶來的一些潛規則,但願能幫到對此感到疑惑的朋友。下面咱們開始進入主題:objective-c
官方 Guide 上只是簡單敘述(Using Swift with Cocoa and Objective-C),即 Swift 編譯器會在咱們使用 Objective-C 的 API 時自動的將其轉成 Swift 風格的 API(說白了就是會對一些方法名、枚舉名等等作一些有規則的刪減,即重命名)。swift
在 Swift 中引用 Objective-C 單例時,若是單例方法包含於類名,則會出現編譯錯誤,下面咱們來看幾個例子。bash
@interface TXLocationManager : NSObject
+ (instancetype)manager;
@end
複製代碼
TXLoginManager
類有一個單例方法命名爲 manager,在 Swift 中引用 manager 方法時,會出現編譯錯誤:ide
說白了,manager 方法已經廢了。。。ui
在 Example 1 的基礎上,咱們把單例方法的命名改一改:spa
@interface TXLocationManager : NSObject
+ (instancetype)shareInstance;
@end
複製代碼
單例方法命名改爲 shareInstance 後,編譯經過了。至此,至少問題已經解決了,如今咱們再簡單看看是什麼緣由?爲什麼 manager 方法沒法引用,而 shareInstance 卻能夠引用呢?3d
在 Example 1 的基礎上,把 manager 單例方法名稱改成 shareManager :code
@interface TXLocationManager : NSObject
+ (instancetype)shareManager;
@end
複製代碼
咱們能夠發如今 Swift 中引用時,shareManager 方法名被重命名爲 share :cdn
至此,咱們能夠得出一個簡單的命名潛規則:在 Swift 中引用 Objective-C 單例時,若是單例方法包含於類名,則會出現編譯錯誤,準確的說,應該是若是單例方法的名稱正好是該類名駝峯命名的後綴,那麼在 Swift 中引用該單例方法時,會出現編譯錯誤。對象
爲什麼在 Swift 中引用 Objective-C 類的 API 會出現這種問題呢?官方 Guide 上時這樣描述的:
The Swift compiler automatically imports Objective-C code as conventional Swift code. It imports Objective-C class factory methods as Swift initializers, and Objective-C enumeration cases truncated names.
由於 Swift 編譯器在使用 Objective-C 的代碼時會自動的將其轉成 Swift 風格的代碼,就是會對一些方法名、枚舉名等等作一些有規則的刪減。
There may be edge cases in your code that are not automatically handled. If you need to change the name imported by Swift of an Objective-C method, enumeration case, or option set value, you can use the NS_SWIFT_NAME macro to customize how a declaration is imported.
根據官方 Guide,上述的這種 case 屬於 特殊的狀況。那如何解決這種問題呢,Swift 提供了一個宏,專門處理咱們遇到的這種 case —— NS_SWIFT_NAME
@interface TXLocationManager : NSObject
+ (instancetype)manager NS_SWIFT_NAME(shareInstance());
@end
複製代碼
這樣,manager 該單例方法,當咱們在 Swift 中引用時,會被重命名爲 shareInstance。
let _ = TXLocationManager.shareInstance()
複製代碼
有時候,咱們在 Swift 中引用 Objective-C 中某個類的 API 時,方法名是可能會被重命名的,下面咱們直接看例子。
@interface TXLocationManager : NSObject
+ (instancetype)managerWithCoordinateY:(CGFloat)y
// Or
// + (TXLocationManager *)managerWithCoordinateY:(CGFloat)y
@end
複製代碼
當該類的類方法返回自身類型的實例對象時,上述的方法會被重命名。應該這樣引用:
// 方式一:
let _ = TXLocationManager.init(coordinateY: 9)
// 方式二:
let _ = TXLocationManager(coordinateY: 9)
// 錯誤引用方式,編譯失敗
let _ = TXLocationManager.manager(withCoordinateY: 9)
複製代碼
經過上述實踐,咱們能夠發現類方法中的 manager 前綴會被刪掉,並且變成了 Swift 中的 init 方法。若是該類的類方法不返回自身類型的實例對象呢?
@interface TXLocationManager : NSObject
+ (void)managerWithCoordinateY:(CGFloat)y;
// Or
// + (NSObject *)managerWithCoordinateY:(CGFloat)y;
// + (CGFloat)managerWithCoordinateY:(CGFloat)y;
@end
複製代碼
經過實踐能夠發現,在 Swift 中是能夠這樣引用的:
TXLocationManager.manager(withCoordinateY: 9)
複製代碼
這種方式的引用同咱們通常的方法引用是一致的,無異同。
實例方法的重命名規則與類方法有點類似,此處就再也不詳述了,感興趣的朋友能夠本身實踐一下。(固然方法的重命名咱們通常均可以經過 NS_SWIFT_NAME
來指定)