Swift 3.0 預告 - 將 Objc 庫轉換成更符合 Swift 語法風格的形式
Swift 3.0 更新越來越臨近,這次更新會給我們帶來很多實用的內容,比如對 Objc 庫的遷移,會更符合 Swift 的語法風格。用過之前版本的 Swift,我們會發現很多 Objc 庫的方法名稱其實還是以 Objc 的風格來命名,而這次 Swift 3.0 的更新會專門處理這個問題。
原因
這個源于一個編號為 SE-0005 的提案,并且已經審核通過。這個方案的提出,源于這樣一個痛點。 Swift 應用于 iOS App 開發,就免不了會依賴于原生的 Cocoa Touch 庫。而由于歷史原因,大家也都知道, iOS 原生庫大多時基于 Objc 來實現的。所以他們的編碼規范也都遵循著 Objc 的規范,諸如函數,方法的命名規則這些,都有自己的一套標準。
而 Swift 3.0 也發布了自己的 API 設計規范 ,同時 Objc 也有自己的 設計規范 , 這樣一來我們使用 Swift 開發 iOS App 的時候,其實總是在游走于兩套規范的 API 之間,對開發者的體驗嘛,就不是很好了。
例子
咱們用一個實際的例子來說明這個問題。 比如 NSString 有這樣一個方法:
let content = listItemView.text.stringByTrimmingCharactersInSet(
NSCharacterSet.whitespaceAndNewlineCharacterSet())
stringByTrimmingCharactersInSet 會剪掉字符串頭尾中的某些字符。從這個方法名中,明顯的可以看出它是以 Objc 規范來命名的。
如果以 Swift 的編碼規范,這個方法其實應該這樣命名:
let content = listItemView.text.trimming(.whitespaceAndNewlines)
從這里可以看出,objc 的命名方式,很多會把函數的返回值類型,以及參數類型都包含在函數名里面。比如我們上面的 stringByTrimmingCharactersInSet 方法。但這和 Swift 命名規則就不同了。而且隨著 Swift 規范的清晰,這個問題就越來越凸顯出來了。
所以 Swift 3.0 才會將這個問題提上日程,并在這個版本中準備解決這個問題。
規則
解決這個問題,肯定不能手動的替換。因為系統庫的方法實在太多了,所以就需要總結出一系列替換規則。根據這些規則將相應的標識替換完成。
那么 Swift 具體是怎么做的呢, 咱們來了解一下。
擴大 swift_name 編譯屬性的應用范圍 - 這個涉及到 Swift 底層的概念,當我們將 Objc 的 API 導入到 Swift 的時候,我們是可以指定一個編譯屬性 swift_name 的。而這個編譯屬性,可以將 Objc 中的標識名稱在 Swift 中以不同的名字表現出來。但在之前的版本中,這個編譯屬性只能對枚舉項和工廠方法有效,這次將會擴大它的范圍。
去除多余的類型名稱- Objc 的編碼規范中,會建議在方法名稱中將參數名和類型也表示出來,而這個在 Swift 中就是多余的,我們前面那個例子也演示了。這個也是著重處理的點。
添加默認參數- 對于 Objc 需要默認參數的地方,會在 Swift 中添加上默認參數,比如一些選項參數:
NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.AllowFragments)
這個 option 參數就會提供默認參數。
添加第一個參數的參數標簽- 為方法的第一個參數添加合適的參數標簽。
在布爾屬性前面加上 is - 在最新的 Swift 規范中,需要在布爾屬性前面加上 is , 而 Objc 規范恰巧不建議使用 is ,所以在 Swift 3 中會將 Objc 遷移過來的布爾屬性,按照 Swift 規范來進行修改。可以參考 Swift 規范中 關于布爾屬性的部分內容 。
值類型變成小寫- 會將 Objc 的屬性值以小寫開頭, 比如 URLHandler 會變為 urlHandler .
下面是一個官方文檔中給出的轉換的例子:
class UIBezierPath : NSObject, NSCopying, NSCoding {
convenience init(ovalInRect: CGRect)
func moveToPoint(_: CGPoint)
func addLineToPoint(_: CGPoint)
func addCurveToPoint(_: CGPoint, controlPoint1: CGPoint, controlPoint2: CGPoint)
func addQuadCurveToPoint(_: CGPoint, controlPoint: CGPoint)
func appendPath(_: UIBezierPath)
func bezierPathByReversingPath() -> UIBezierPath
func applyTransform(_: CGAffineTransform)
var empty: Bool { get }
func containsPoint(_: CGPoint) -> Bool
func fillWithBlendMode(_: CGBlendMode, alpha: CGFloat)
func strokeWithBlendMode(_: CGBlendMode, alpha: CGFloat)
func copyWithZone(_: NSZone) -> AnyObject
func encodeWithCoder(_: NSCoder)
}
轉換后:
class UIBezierPath : NSObject, NSCopying, NSCoding {
convenience init(ovalIn rect: CGRect)
func move(to point: CGPoint)
func addLine(to point: CGPoint)
func addCurve(to endPoint: CGPoint, controlPoint1 controlPoint1: CGPoint, controlPoint2 controlPoint2: CGPoint)
func addQuadCurve(to endPoint: CGPoint, controlPoint controlPoint: CGPoint)
func append(_ bezierPath: UIBezierPath)
func reversing() -> UIBezierPath
func apply(_ transform: CGAffineTransform)
var isEmpty: Bool { get }
func contains(_ point: CGPoint) -> Bool
func fill(_ blendMode: CGBlendMode, alpha alpha: CGFloat)
func stroke(_ blendMode: CGBlendMode, alpha alpha: CGFloat)
func copy(with zone: NSZone = nil) -> AnyObject
func encode(with aCoder: NSCoder)
}
是不是感覺方法名清晰很多呢。
總結
以上就是 Swift 3 對 Objc 依賴庫中的優化了,這次優化后,我們以后在用 Swift 來開發 iOS App 的時候,就不會再混合兩種代碼風格啦。
來自: http://www.swiftcafe.io/2016/05/07/swift3-objc/