OC和Swift混編經驗

zeqinjie發表於2018-09-10

github地址

Swift簡介

Swift,蘋果於2014年WWDC(蘋果開發者大會)釋出的新開發語言,可與Objective-C*共同執行於Mac OS和iOS平臺,用於搭建基於蘋果平臺的應用程式。 2015年12月4日,蘋果公司宣佈其Swift程式語言現在開放原始碼

Swift 優勢

簡潔程式碼

  1. Swift所有的變數定義使用var ,常量定義使用let。
  2. 陣列或字串可以使用"+"符號直接相加。
  3. 可以使用高階函式map,flatMap,reduce,filter簡化程式碼量。

易維護

  1. Swift拋棄了OC標頭檔案(.h)和實現檔案(.m)組合成一個程式碼檔案(.swift)。
  2. 因為Swift不是基於C構建的,而OC是在C和Smalltalk下構建。所以在設計上比較新穎,同時我們能看到現代語言(JavaScript,Java,Python,C#,以及 C++ )的身影特性:泛型,可選型別,型別推斷,高階函式。基於泛型和高階函式的使用導致更清晰,更可重用的程式碼,更易於維護。

安全

  1. 在OC中不同型別可以直接相加,預設會隱式轉換。但是swift不同型別的是不能直接相加,必須先進行型別轉換。
  2. 在其他的程式語言當中,你並不能知道哪個變數可以為空(null)哪個不能,這就強制開發者去考慮可能為空的情況。
  3. 在OC中if判斷存在非0即是true的方式,但是在swift中if判斷必須為true或者false。

  1. OC是一門動態的語言,很多實際執行需要在執行時才可以確定,Swift不一樣,Swift將很多在執行時才可以確定的資訊,在編譯期就決定了。這就讓Swift更加快速。Swift效能探索和優化分析-王巍
  2. 在純Swift中的函式呼叫就不是OC的那套runtime了,而是類似C++的vtable,在編譯期就決定呼叫哪個函式。那如果想使用OC的特性需要繼承自NSObject。

Swift 與 OC 的混編

  1. 當我們在OC專案中新增Swift檔案的時候系統會預設幫我建立一個橋接檔案。 “專案名稱-Bridging-Header.h”的檔案。
  2. 在Swift中呼叫OC的類時,只需要在上面橋接標頭檔案import即可
  3. 在OC中呼叫Swift類,則需在OC檔案中import "專案名稱-Swift.h" 標頭檔案即可

混合開發的問題

最近有個新聞列表改版需求,那在此下使用Swift去重做這塊需求,需求中遇到一些坑和大家分享下。

  • 數模轉換的坑

在OC專案中常用的MJExtension第三方庫。那在swift中我們怎麼做呢? 當然可以使用目前第三方庫SwiftJson或者HandyJSON或者實現Codable協議。不過這裡我使用的是系統KVC方式,遇到問題如下

  1. 因為swift的建構函式與OC不一樣,當子類中有自己的建構函式時,那麼將不繼承父類自定義的建構函式。所以子類需重寫父類init(dict : [String : Any])這個建構函式否則將無法使用。
  2. 因為使用的是NSObject的KVC特性所以需加@objc定義子類屬性。注意在swift4.0之前預設只要繼承NSObject就會系統預設新增,但這之後需要手動新增了。
class BaseModel: NSObject {
    override init() {
    }
    
    init(dict : [String : Any]) {
        super.init()
        setValuesForKeys(dict)
    }
    //記得重寫該方法避免崩潰
    override func setValue(_ value: Any?, forUndefinedKey key: String) {}
}

class NewsNavModel: BaseModel {
    //type = 998 最新,999 收藏
    @objc var type:Int = 0
    @objc var type_name:String = ""
    
    init(_ type : Int , type_name : String) {
        super.init()
        self.type = type
        self.type_name = type_name
    }
    //需重寫父類方法
    override init!(dic: [String : Any]!) {
        super.init(dic: dic)
    }
}

複製程式碼
  • 關於@objc坑
  1. 在swift3使用#selector指定的方法,只有當方法許可權為private時需要加@objc修飾符,現在Swift4.0全都要加@objc修飾符
  2. 定義的方法,列舉,協議或者是屬性如果需要被OC呼叫則需新增@objc
  3. 自定義的protocol協議中,有optional修飾的非必須實現的方法,需要用@objc修飾
  • 被廢棄的方法:

initialize/dispatch_once方法已經被Swift4.0廢棄所以後續不能再使用

  • NSClassFromString方法的坑

在OC的時候直接使用類名即可轉換為對於Class,但是Swift中有名稱空間存在所以使用這個方法需要新增專案的名稱

//OC 中
Class ocClass = NSClassFromString(@"MyFavModel");

//Swift中
let swiftClass = NSClassFromString("專案名稱.MyFavModel") 
複製程式碼
  • fatalError

在Swift 中繼承了遵守NSCoding protocol的類時,並自定義建構函式時候則需加入required init(coder aDecoder: NSCoder)。這個是在OC中則不存在的。 其作用是表明子類不能通過被fatalError定義的函式做初始化

override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
    super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
    self.hidesBottomBarWhenPushed = true
}

required init(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}
複製程式碼
  • OC的類不能繼承至Swift的類,但是Swift類可以繼承至OC的類。

補充:即使Swift的父類是OC也不能讓OC類繼承該Swift類

  • Swift中沒有巨集,只能使用全域性常量或者全域性函式替代。
/// 當前app資訊
let AppInfo = Bundle.main.infoDictionary

/// 當前app版本號
let AppCurrentVersion = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as! String

/// 日誌列印
func DLog(str: String) {
    #if DEBUG
    print("file: \(#file), line:\(#line),\(str)")
    #endif
}
複製程式碼
  • Swift不像OC那樣能直接呼叫C++,需通過OC或者C去呼叫C++。

其他

Swift版本升級

例如:Swift3.0 -> Swift4.0

  1. 選中要轉換的 target
  2. Edit -> Convert -> To Current Swift Syntax
  3. 勾選需要轉換的 target (pod 引用不用勾選),Next
  4. 選擇轉換選項,Next

image

快速的將OC語言轉換成Swift語言

這裡推薦一款swiftify外掛。支援線上轉換,或者新增外掛到Xcode中。

  1. 外掛安裝AppStore下載地址
  2. 線上轉換地址

image

快速將json轉化為Swift的模型物件

基於Codable協議快速的數模序列化

  1. 它不僅支援Swift,還支援其他語言比如Kotlin,Java,C#,Ruby,Object-c,Python
  2. 線上連結

image

通過R.swift快速生成資原始碼

根據專案內容來自動化生 ImageName 和 SegueName程式碼 可以使用Switf的自動化工具了,R.swiftSwiftGen

let image = UIImage(imageName: .imgIcon)
複製程式碼

推薦

Swift學習文件:

  1. The Swift Programming Language (Swift 4)
  2. Swift的180個介紹

Swift 書籍

  1. Swifter - Swift 必備 tips
  2. Swift 進階

參考地址

  1. Swift4.0新特性

相關文章