本文主要是筆者小結 WWDC2017 中 《What's New in Swift》的 Session ,其中也摻雜了些《What’s New in Foundation》,僅做記錄。html
下面步入主題。git
SE-0169github
在 Swift 4 中,private 修飾的屬性能夠在 Extension 中訪問了,不再要用 fileprivate 修飾屬性了😎。json
下面咱們來區分 Swift 3 與 Swift 4 中的區別。swift
Swift 3:api
Swift 4:
數組
SE-0156微信
在 Swift 3 中,有些童鞋使用代理時,沒法同時繼承類和協議app
Swift 4 中,針對此處進行了改進,直接上 WWDC17 示例代碼:ide
func shareEm(control: UIControl & Shakeable) { control.share() } protocol Shakeable { func share() } extension Shakeable { func share() { print("starting share!") } } extension UIButton: Shakeable { } extension UISlider: Shakeable { }
在 Swift 4 中新增了一種 Key-Path 表達式,該表達式可用於 KVC & KVO 中的 APIs,格式以下:
\[Type Name].[Property Name]
示例代碼以下:
struct SomeStructure { var someProperty: Int } func smartKeyPath() { let s = SomeStructure(someProperty: 12) let keyPath = \SomeStructure.someProperty let value = s[keyPath: keyPath] print(value) // value is 12 }
若是在上下文中,能隱含的推斷出其類型,那麼 Key-Path 表達式中的 Type Name 能夠省略,即
\.[Property Name]
如:
@objcMembers class SomeClass: NSObject { dynamic var someProperty: Int init(someProperty: Int) { self.someProperty = someProperty } } var observe: NSKeyValueObservation? let c = SomeClass(someProperty: 10) func smarkKVO() { observe = c.observe(\.someProperty) { object, change in // ... print(object.someProperty, change) } c.someProperty = 10 }
Excerpt From: Apple Inc. 「Using Swift with Cocoa and Objective-C (Swift 4 beta).
咱們如下面這段 JSON 爲例,來看 Swift 4 中針對 JSON 進行解析的新方法
{ "name": "Banana", "points": 200, "description": "A banana grown in Ecuador.", "varieties": [ "yellow", "green", "brown" ] }
首先,咱們要遵循 Codable 協議:
struct GroceryProduct: Codable { let name: String let points: Int let description: String let varieties: [String] }
使用 JSONDecoder 進行解析:
let json = """ { "name": "Banana", "points": 200, "description": "A banana grown in Ecuador.", "varieties": [ "yellow", "green", "brown" ] } """.data(using: .utf8)! let decoder = JSONDecoder() let banana = try! decoder.decode(GroceryProduct.self, from: json) print("\(banana.name) (\(banana.points) points): \(banana.description)") // Prints "Banana (200 points): A banana grown in Ecuador.
本節主要展現 JSONEncoder 編碼,直接上代碼:
struct University: Codable { enum Level: String, Codable { case one, two, three } var name: String var founds: Int var type: Level } func codableTest (_ obj: University) { let encoder = JSONEncoder() let decoder = JSONDecoder() guard let data = try? encoder.encode(obj) else { return } guard let jsonData = try? decoder.decode(University.self, from: data) else { return } print("jsonData:", jsonData) }
在 Swift 4 中,修復了字形羣集長度計算的一些問題,如 emoji 表情。關於字形羣集或者 Unicode 編碼概念生疏的童鞋能夠看筆者以前寫的兩篇文章 《字符編碼(一)》、《Swift3.0 中 Strings/Characters 閒聊》。下面咱們來看看 WWDC17 上的的示例:
var family = "👩" family += "\u{200D}👩" family += "\u{200D}👧" family += "\u{200D}👧" print("\(family):\(family.count)") // result --> 👩👩👧👧:1
在以前 family.count 會等於 4(\u{200D} 是一個零寬度的 joiner)。
筆者在 Xcode 9 beta1 上運行,選擇 Swift 編譯語言版本時,測試結果無效,只有在 Xcode 8 測試時 family.count = 4。
在 Swift 2 中,String 的集合這一特性被遺棄,在 Swift 3 中,String 也沒有遵照集合的相關協議(如:RangeReplaceableCollection, BidirectionalCollection),所以自 Swift 2 起,String 不是一個集合,而是把這一特性賦予給了 String 的一個屬性 --> characters (A view of the string’s contents as a collection of characters.),該屬性是 String.CharacterView 類型,而且遵照 RangeReplaceableCollection 協議。
extension String.CharacterView : RangeReplaceableCollection {···}
所以咱們在遍歷或者操做 String 時,常常會這麼寫:
Excerpt From: Apple Inc. 「The Swift Programming Language (Swift 3.1).」 iBooks. https://itunes.apple.com/us/book/the-swift-programming-language-swift-3-1/id881256329?mt=11
for character in "Dog!🐶".characters { print(character) } // D // o // g // ! // 🐶
.characters.····。
但,直至 Swift 4,String 又開始遵循集合相關協議,今後能夠這麼寫了:
for character in "Dog!🐶" { print(character) } // D // o // g // ! // 🐶
固然在 Swift 4 中又出現了一個新的結構體 Substring,Substring 沒法直接賦值給 String 的。
關於 Substring 與 String 之間的轉換能夠這麼寫:
let label = UILabel() let superStr = "tingxins" let subStr = superStr.prefix(4) label.text = String(subStr) print(subStr)
若是字符串須要跨多行,能夠這麼寫:
Excerpt From: Apple Inc. 「The Swift Programming Language (Swift 4).」.
let quotation = """ The White Rabbit put on his spectacles. "Where shall I begin, please your Majesty?" he asked. "Begin at the beginning," the King said gravely, "and go on till you come to the end; then stop." """
沒錯,三對引號。
若是字符串自己包含三個連續的 ‘"""‘ 引號時,能夠採用反斜槓進行轉義處理(),如:
let threeDoubleQuotes = """ Escaping the first quote \""" Escaping all three quotes \"\"\" """
在 Swift 3 中,區間運算符只有兩種:閉區間運算符(Closed Range Operator)、半閉區間運算符(Half-Open Range Operator)。在 Swift 4 中,又新增了一種更加簡單方便的區間運算符-->單面區間(One-Sided Ranges)。
Excerpt From: Apple Inc. 「The Swift Programming Language (Swift 4).
你能夠這樣寫:
let names = ["Anna", "Alex", "Brian", "Jack"] for name in names[2...] { print(name) } // Brian // Jack for name in names[...2] { print(name) } // Anna // Alex // Brian
固然也和結合半閉區間運算符,能夠這麼寫:
for name in names[..<2] { print(name) } // Anna // Alex
判斷區間是否包含,能夠這麼寫:(for語句中要注意死循環哈)
let range = ...5 range.contains(7) // false range.contains(4) // true range.contains(-1) // true」
WWDC17 示例代碼:
在 Swift 3 中,假設咱們要爲 Sequence 擴展一個方法,要這麼寫:
extension Sequence where Iterator.Element: Equatable { func containsOnly(_ value: Iterator.Element) -> Bool { return contains { (element) -> Bool in return element == value } } }
但在 Swift 4 中, 針對 Sequence 作了一些小改進,使咱們代碼更加輕便,看起來更加清爽:
extension Sequence where Element: Equatable { func containsOnly(_ value: Element) -> Bool { return contains { (element) -> Bool in return element == value } } }
這是怎麼實現的呢?由於在 Swift 4 中,咱們在聲明一個 associatedtype 的 placeholder 時,咱們可使用 where 語句了。
下面咱們來對比一下 Swift 3 與 Swift 4 中 Sequence 的區別:
在 Swift 3 中 Sequence 協議是這麼寫的:
在 Swift 4 中進行改進後,是這麼寫的:
對比看完後,想必讀者一目瞭然。
下面針對 associatedtype 中使用 where 語句,咱們再來看個例子:
Excerpt From: Apple Inc. 「The Swift Programming Language (Swift 4).
protocol Container { associatedtype Item mutating func append(_ item: Item) var count: Int { get } subscript(i: Int) -> Item { get } associatedtype Iterator: IteratorProtocol where Iterator.Element == Item func makeIterator() -> Iterator }
若是在 Swift 3 下寫,Xcode 會出現這樣的編譯錯誤:
有了上面這些特性後,咱們在使用 Swift 4 時,能夠省略一些冗餘約束,這裏直接上 WWDC17 的示例代碼:
在 Swift 3 中,是這樣寫的:
在 Swift 4 中,如今咱們能夠這麼寫:
在 Swift 4 中,如今支持泛型下標了,直接上代碼:
Excerpt From: Apple Inc. 「The Swift Programming Language (Swift 4).
extension Container { subscript<Indices: Sequence>(indices: Indices) -> [Item] where Indices.Iterator.Element == Int { var result = [Item]() for index in indices { result.append(self[index]) } return result } }
上述代碼咱們爲 Container 添加了下標取值能力,在這個泛型下標中有 3 個約束:
Swift 3 中,NSNumber 轉換有個 Bug,如:
let n = NSNumber(value: UInt32(543)) let v = n as? Int8 // v is 31
Swift 4 中已修復:
如今可變集合增長了一個方法,咱們能夠直接使用 swapAt 方法,而非 swap 。
let university0 = University(name: "Qsting", founds: 1870, type: .one) let university1 = University(name: "tingxins", founds: 1870, type: .one) var mutableCollection = [university0, university1] print(mutableCollection) mutableCollection.swapAt(0, 1) //交換數組中0、1元素的位置 print(mutableCollection)
歡迎關注微信公衆號