国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Swift > 正文

Swift 4最全的新特性詳細解析(推薦)

2020-03-09 17:43:35
字體:
來源:轉載
供稿:網友

引言

Swift,蘋果于2014年WWDC(蘋果開發者大會)發布的新開發語言,可與Objective-C共同運行于Mac OS和iOS平臺,用于搭建基于蘋果平臺的應用程序。Swift吸收了眾多現代編程語言的優點,盡力的提供簡潔的編程語言和強大的功能。

WWDC 2017 給大家帶來了很多驚喜。Swift 4 也伴隨著 Xcode 9 測試版來到了我們的面前,很多強大的新特性非常值得我們期待在正式項目中去使用它。因為 Swift 4 是開源的,如果你關注 swift-evolution 這個項目的話,就應該已經提前了解到它的新特性了。本文參考了 WWDC 2017 以及各種資料,,從語法、字符串、標準庫、構建過程等方面,把 Swift 4 的這些新特性一一列舉出來做介紹和分析,讓他們毫無保留地展現在你眼前,下面話不多說了,來隨著小編一起看看詳細的介紹吧。

一、語法改進

extension 中可以訪問 private 的屬性

考慮以下代碼:

struct Date: Equatable, Comparable { private let secondsSinceReferenceDate: Double static func ==(lhs: Date, rhs: Date) -> Bool { return lhs.secondsSinceReferenceDate == rhs.secondsSinceReferenceDate } static func <(lhs: Date, rhs: Date) -> Bool { return lhs.secondsSinceReferenceDate < rhs.secondsSinceReferenceDate }}

上面代碼定義了一個 Date 結構體,并實現 Equatable 和 Comparable 協議。為了讓代碼更清晰,可讀性更好,一般會把對協議的實現放在單獨的 extension 中,這也是一種非常符合 Swift 風格的寫法,如下:

struct Date { private let secondsSinceReferenceDate: Double}extension Date: Equatable { static func ==(lhs: Date, rhs: Date) -> Bool { return lhs.secondsSinceReferenceDate == rhs.secondsSinceReferenceDate }}extension Date: Comparable { static func <(lhs: Date, rhs: Date) -> Bool { return lhs.secondsSinceReferenceDate < rhs.secondsSinceReferenceDate }}

但是在 Swift 3 中,編譯就報錯了,因為 extension 中無法獲取到 secondsSinceReferenceDate 屬性,因為它是 private 的。于是在 Swift 3 中,必須把 private 改為 fileprivate。

struct Date { fileprivate let secondsSinceReferenceDate: Double}...

但是如果用 fileprivate,屬性的作用域就會比我們需要的更大,可能會不小心造成屬性的濫用。

在 Swift 4 中,private 的屬性的作用域擴大到了 extension 中,并且被限定在了 struct 和 extension 內部,這樣就不需要再改成 fileprivate 了,這是最好的結果。

類型和協議的組合類型

考慮以下代碼:

protocol Shakeable { func shake()}extension UIButton: Shakeable { /* ... */ }extension UISlider: Shakeable { /* ... */ }func shakeEm(controls: [???]) { for control in controls where control.state.isEnabled { } control.shake()}

在 Swift 3 中,這里的 ??? 應該寫什么呢?如果寫 UIControl,那么 control.shake() 就會報錯;如果寫 Shakeable,那么 control.state.isEnabled 就會報錯。其實我們也可以這樣寫:

func shakeEm(controls: [UIControl]) { for control in controls where control.isEnabled { if control is Shakeable {  (control as! Shakeable).shake() } }}

這樣寫雖然可以跑通了,但是很丑陋。

在 Swift 4 中,可以把類型和協議用 & 組合在一起作為一個類型使用,就可以像下面這樣寫了:

protocol Shakeable { func shake()}extension UIButton: Shakeable { /* ... */ }extension UISlider: Shakeable { /* ... */ }func shakeEm(controls: [UIControl & Shakeable]) { for control in controls where control.state.isEnabled { control.shake() }// Objective-C API@interface NSCandidateListTouchBarItem<CandidateType> : NSTouchBarItem@property (nullable, weak) NSView <NSTextInputClient> *client;@end}

把它聲明為了 UIControl & Shakeable 類型。OK,圓滿解決。

PS:

這個代碼例子是 WWDC 2017 的 PPT 中的,上面的代碼有點問題,control.state.isEnabled 這句代碼中,state 是沒有 isEnabled 這個屬性的,改為 control.isEnabled 就可以了。看來蘋果的工程師做 PPT 有時候還是不太嚴謹。

另外,iOS SDK 中的 API 也用這個特性做了優化,例如:

// Objective-C API@interface NSCandidateListTouchBarItem<CandidateType> : NSTouchBarItem@property (nullable, weak) NSView <NSTextInputClient> *client;@end

這個 API 的 Objective-C 版本是沒有問題的,可以知道 client 屬性既是一個 NSView,又符合 NSTextInputClient 協議。然而它對應的 Swift 3 版本為:

class NSCandidateListTouchBarItem<CandidateType: AnyObject> : NSTouchBarItem { var client: NSView?}

僅僅是一個 NSView 類型 /(ㄒoㄒ)/~~

在 Swift 4 中,這類 API 做了優化,改成了:

class NSCandidateListTouchBarItem<CandidateType: AnyObject> : NSTouchBarItem { var client: (NSView & NSTextInputClient)?}

這樣類型的聲明就更加嚴謹了。

Associated Type 可以追加 Where 約束語句

在 Swift 4 中可以在 associatedtype 后面聲明的類型后追加 where 語句

associatedtype Element where <xxx>

看下面是 Swift 4 標準庫中 Sequence 中 Element 的聲明:

protocol Sequence { associatedtype Element where Self.Element == Self.Iterator.Element // ...}

它限定了 Sequence 中 Element 這個類型必須和 Iterator.Element 的類型一致。

通過 where 語句可以對類型添加更多的約束,使其更嚴謹,避免在使用這個類型時做多余的類型判斷。

新的 Key Paths 語法

先來看看 Swift 3 中 Key Paths 的寫法:

@objcMembers class Kid: NSObject { dynamic var nickname: String = "" dynamic var age: Double = 0.0 dynamic var friends: [Kid] = []}var ben = Kid(nickname: "Benji", age: 5.5)let kidsNameKeyPath = #keyPath(Kid.nickname)let name = ben.valueForKeyPath(kidsNameKeyPath)ben.setValue("Ben", forKeyPath: kidsNameKeyPath)

Swift 4 中創建一個 KeyPath 用 `` 作為開頭:

/Kid.nickname

當編譯器可以推導出類型時,可以省略基礎類型部分:

/.nickname

上面的代碼在 Swift 4 中就可以這樣寫:

struct Kid { var nickname: String = "" var age: Double = 0.0 var friends: [Kid] = []}var ben = Kid(nickname: "Benji", age: 8, friends: [])let name = ben[keyPath: /Kid.nickname]ben[keyPath: /Kid.nickname] = "BigBen"

相比 Swift 3,Swift 4 的 Key Paths 具有以下優勢:

  1. 類型可以定義為 class、struct
  2. 定義類型時無需加上 @objcMembers、dynamic 等關鍵字
  3. 性能更好
  4. 類型安全和類型推斷,例如 ben.valueForKeyPath(kidsNameKeyPath) 返回的類型是 Any,ben[keyPath: /Kid.nickname] 直接返回 String 類型
  5. 可以在所有值類型上使用

下標支持泛型

有時候會寫一些數據容器,Swift 支持通過下標來讀寫容器中的數據,但是如果容器類中的數據類型定義為泛型,以前的下標語法就只能返回 Any,在取出值后需要用 as? 來轉換類型。Swift 4 定義下標也可以使用泛型了。

struct GenericDictionary<Key: Hashable, Value> { private var data: [Key: Value] init(data: [Key: Value]) { self.data = data } subscript<T>(key: Key) -> T? { return data[key] as? T }}let dictionary = GenericDictionary(data: ["Name": "Xiaoming"])let name: String? = dictionary["Name"] // 不需要再寫 as? String

二、字符串

Unicode 字符串在計算 count 時的正確性改善

在 Unicode 中,有些字符是由幾個其它字符組成的,比如 é 這個字符,它可以用 /u{E9} 來表示,也可以用 e 字符和上面一撇字符組合在一起表示 /u{65}/u{301}。

考慮以下代碼:

var family = "
注:相關教程知識閱讀請移步到swift教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 大港区| 自治县| 新竹县| 镇远县| 封开县| 西吉县| 新乐市| 西吉县| 南川市| 都匀市| 射洪县| 泸溪县| 巢湖市| 互助| 崇阳县| 合作市| 禄劝| 北京市| 含山县| 兴化市| 内乡县| 施秉县| 湖南省| 绵阳市| 绵竹市| 衢州市| 蓬安县| 汝南县| 西平县| 绥棱县| 子洲县| 喜德县| 安徽省| 疏附县| 郸城县| 平乐县| 郁南县| 班玛县| 巴楚县| 万源市| 泗水县|