Swift 2.1-3.1版本演進匯總

有一段時間沒有寫 Swift 了, 前段時間打算在工程中使用 Swift, 結(jié)果發(fā)現(xiàn)各種東西都變了, 由于點比較分散, 而且官方文檔沒有給出具體例子, 只是羅列了修改點, 有些點還不太好理解, 所以自己整理了一下變化, 主要是2.1-3.1的修改, 后續(xù)的更新應該也會繼續(xù)往下面添加, 不過排版的形式還在考慮是最新的排最上面還是最下面...

有必要舉出例子的都會盡量舉出的例子, 其它的個人覺得沒什么特別的就會翻譯略過, 具體還是要參考官網(wǎng)的 Revision History. 如有疑問或者錯漏, 希望留言, 大家一起交流.

Swift 2.2更新

*增加了條件編譯塊的內(nèi)容

相當于增加了 C 語言里面的條件編譯宏, 這部分內(nèi)容在后續(xù)的版本中還有增強, #if, #elseif, #else, #endif都和之前沒有太大的變化, 主要還是條件有比較多的修改, 可以支持 os 類型和版本, arch, 后續(xù)還增加了 Swift 的版本.

*在指定成員描述(Explicit Member Expression)小節(jié)中, 增加了僅僅通過名字和參數(shù)來區(qū)分方法/構(gòu)造器的內(nèi)容

標題比較難理解, 其實就是在2.2中判定方法重名的機制變了, 直接看例子:

class SomeClass {
    func someMethod(x: Int, y: Int) {}
    func someMethod(x: Int, z: Int) {}
    func overloadedMethod(x: Int, y: Int) {}
    func overloadedMethod(x: Int, y: Bool) {}
}
let instance = SomeClass()
 
let a = instance.someMethod              // 無法確定
let b = instance.someMethod(x:y:)        // 可以確定
 
let d = instance.overloadedMethod        // 無法確定
let d = instance.overloadedMethod(x:y:)  // 依然無法確定
let d: (Int, Bool) -> Void  = instance.overloadedMethod(x:y:)  // 可以確定

可以看到, 參數(shù)名也需要一致了, 如果參數(shù)名一致, 但是類型不一致則需要顯式寫上方法的類型.

*增加了#selector的形式獲取 selector

之前的版本都是用字符串來尋找 selector, 沒有提示, 很容易出錯, 而且不報錯, 比較坑爹, 2.2增加了用#selector尋找 selector

*在關聯(lián)類型和協(xié)議關聯(lián)類型小節(jié)中更新了用 associatedtype 來關聯(lián)類型的內(nèi)容
// 2.2 以前
protocol Container {
    typealias ItemType  // <-- 之前為 typealias
    mutating func append(item: ItemType)
    var count: Int { get }
    subscript(i: Int) -> ItemType { get }
}

// 2.2
protocol Container {
    associatedtype Item // <-- 修改為 associatedtype
    mutating func append(_ item: Item)
    var count: Int { get }
    subscript(i: Int) -> Item { get }
}
*更新了構(gòu)造失敗小節(jié)中構(gòu)造器在實例完全構(gòu)造好之前返回 nil 的內(nèi)容

仔細看了一下文檔中給出的例子, 沒有發(fā)現(xiàn)明顯的區(qū)別, 所以具體也不知道更新了哪里...

*在比較操作符小節(jié)中增加了元組的對比

元組的對比需要兩邊里面的類型是一致, 否則會報錯. 直接看官方的例子吧

(1, "zebra") < (2, "apple")   // true, 因為1<2, 后續(xù)的就不會比了
(3, "apple") < (3, "bird")    // true, 因為3==3, apple<bird
(4, "dog") == (4, "dog")      // true

(1,2) < ("aa", "bb") // error

*在關鍵字和標點小節(jié)中,增加了使用關鍵字作為外部參數(shù)名的內(nèi)容

也就是說現(xiàn)在關鍵字作為參數(shù)的標簽也是可以的了. 如:

func keywordFunc(func x: Int, while y: String){}
*在聲明屬性小節(jié)中更新了關于 @objc 屬性的內(nèi)容, 現(xiàn)在枚舉和它的 case 都可以使用這個屬性了

這里增加了一大段描述, 大概就是現(xiàn)在可以給枚舉加 @objc 屬性了, 然后如果要在 Objc 代碼里面使用的話, 類型會自動拼接為 {TYPE}{CASE}, 如:

// xxx.swift
@objc public enum SomeType: Int {
    case Custom
    case System
    case TypeOne
    case None
}

// xxx.m
SomeType type = SomeTypeCustom;

對 case 使用 @objc 沒有做多余的闡述, 應該和 class 的屬性用是一致的效果.

*更新了操作符小節(jié)中, 關于自定義操作符中包含點的內(nèi)容

現(xiàn)在可以定義一個以點(.)開頭的操作符, 例如: 可以定義.+.操作符, 它會被當做一個獨立的操作符. 如果一個自定義操作符不是以.開頭的, 那么它也不能在后續(xù)中包含., 例如+.+會被當做是+后面跟著一個.+操作符

PS: 個人不太建議定義這種奇奇怪怪的操作符, 如果不能一眼看出其作用或者符合一般的認知習慣, 就會變成定義了一個函數(shù)叫 a 一樣無法理解.

*還是在重新拋出函數(shù)和方法小節(jié)中, 增加了重新拋出函數(shù)不能直接拋出錯誤

也就是說標記為rethrows的函數(shù)不能直接 throw 一個錯誤, 必須要在 do-catch 中拋出, 如:

func someFunction(callback: () throws -> Void) rethrows {
    do {
    
    } catch {
        throw AnotherError.error
    }
}
*在屬性監(jiān)聽小節(jié)中, 增加了傳入 in-out 參數(shù)的時候, 觸發(fā)屬性監(jiān)聽的內(nèi)容

我覺得這算是之前的一個小bug, 老版本在傳入屬性作為 in-out 參數(shù)的時候并不會調(diào)用 willSet 和 didSet, 3.0解決了這個問題:

class Test {
    var num = 1 {
        didSet{
            print("will set")
        }
        willSet{
            print("did set")
        }
    }
}

func testInout( param x : inout Int ){
    x = 2
}

var test = Test()
testInout(param: &test.num)

*在 A Swift Tour中增加了錯誤處理

在Swift 簡介中增加了錯誤處理的小節(jié)

*更新了弱引用的圖標, 使得析構(gòu)過程更加清晰
*移除了 C 風格的 for 循環(huán), 前++, 后++和前--, 后--都被移除了
*移除了可變函數(shù)參數(shù)和柯里化函數(shù)的特殊語法

Swift 3.0 變動

// 2017.1.7增加

* GCD 的修改

GCD 在 Swift 3中得到了徹底的修改, 新語法更適合 Swift 的寫法. 例如:

DispatchQueue.global().async {
    // do something in global queue
}
 
DispatchQueue.main.async {
    // do something in main queue   
}

具體 GCD 使用細節(jié)可以看看WWDC 視頻或者官方文檔

*更新了函數(shù)章節(jié)的內(nèi)容, 函數(shù)聲明小節(jié)中所有的參數(shù)都會默認獲得一個參數(shù)標簽了.

以下列代碼為例:

// 函數(shù)聲明未變
func someFunction(firstParameterName: Int, secondParameterName: Int) {

}

// 3.0前版本調(diào)用
someFunction(1, secondParameterName: 2)

// 3.0版本調(diào)用
someFunction(firstParameterName: 1, secondParameterName: 2)
*更新了高級操作符章節(jié)內(nèi)容, 現(xiàn)在可以把自定義的操作符作為類型方法來定義了, 而不是之前的全局函數(shù).

高級操作符之前沒有在系列文章中體現(xiàn), 所以暫時不好對比了, 如果可能的話我把以前的文檔找出來對比一下. 總之, 看起來現(xiàn)在友好很多, 以前看 swift 的源碼的時候會發(fā)現(xiàn)一大堆的操作符定義...

*在訪問控制章節(jié)中增加了對 open 和 fileprivate 的解釋.

也就是說訪問控制又增加了2個級別, 之前 private 對應了現(xiàn)在的 fileprivate, 列一個列表來說明變化吧:

修飾符 3.0以前版本 3.0版本
open 與 public 一樣, 可以被外部引用
public 跨模塊可見 跨模塊可見
internal 模塊內(nèi)部的任何源文件可見 模塊內(nèi)部的任何源文件可見
private 同一個源文件內(nèi)可見 當前類型可見
fileprivate 同一個源文件內(nèi)可見

在3.0中 open 相比較于 public 的區(qū)別如下:

 1. open 僅可用于類以及類的成員變量
 2. 用 public 或者更嚴格的訪問級別定義的類, 只能在當前模塊(定義該類的模塊)被繼承
 3. 用 public 或者更嚴格的訪問級別定義的類成員變量, 只能在當前模塊被重載
 4. 用 open 定義的類既可以在當前模塊繼承, 也可以在任意引入該模塊的地方繼承
 5. 用 open 定義的類成員變量既可以在當前模塊重載, 也可以在任意引入該模塊的地方重載

上述的幾點變化都設計到繼承, 重載, 所以 open 僅可用于類和類的成員變量.

*函數(shù)中 inout 修飾符的位置發(fā)生了變化
// 3.0前
func swapTwoInts(inout a: Int, inout _ b: Int) {
    let t = a
    a = b
    b = t
}
var a = 1, b = 2
swapTwoInts(&a, &b)  // &去掉會報錯

// 3.0
var x = 10
func f(a: inout Int, b: inout Int) {
    a += 1
    b += 10
}
f(a: &x, b: &x) // Invalid, in-out arguments alias each other
*更新了逃逸閉包和自動閉包章節(jié)的 @noescape@autoclosure 的信息, 目前它們是類型信息, 而不是聲明屬性了.

@noescape被去除, 增加了正向表意的 @escaping, 位置也有所變化.

// 3.0以前
var completionHandlers: [() -> Void] = [] // 存儲閉包用
func someFunctionWithNoescapeClosure(@noescape closure: () -> Void) {
 closure()
 completionHandlers.append(closure) // error
}
func someFunctionWithEscapingClosure(completionHandler: () -> Void) {
 completionHandlers.append(completionHandler)
}

// 3.0
var completionHandlers: [() -> Void] = []
func someFunctionWithEscapingClosure(completionHandler: @escaping () -> Void) {
    completionHandlers.append(completionHandler)
}

@autoclosure沒有更名, 只是和 @escaping 一樣變了位置

// 3.0以前
func serveCustomer(@autoclosure customerProvider: () -> String) {
 print("Now serving \(customerProvider())!")
}
serveCustomer(customersInLine.removeAtIndex(0))

// 3.0
func serve(customer customerProvider: @autoclosure () -> String) {
    print("Now serving \(customerProvider())!")
}
serve(customer: customersInLine.remove(at: 0))
*高級操作符章節(jié)增加了自定義 infix 操作符優(yōu)先級組的信息

直接看文檔吧, 目前不打算深入了解, 看文檔

*一系列更新, 包括用 macOS 取代 OS X, Error 替代 ErrorProtocol, 諸如ExpressibleByStringLiteral的協(xié)議改名為StringLiteralConvertible.
*更新了泛型章節(jié)的 where語句中的泛型小節(jié), 現(xiàn)在 where 語句被寫在了聲明的最后邊

直接看代碼對比來看where語句的變化吧

// 3.0以前
func allItemsMatch<
    C1: Container, C2: Container  // <-- 類型約束, 必須實現(xiàn)Container
    where C1.ItemType == C2.ItemType, C1.ItemType: Equatable> // <-- 協(xié)議內(nèi)部關聯(lián)類型必須相等, 關聯(lián)類型必須實現(xiàn)Equatable協(xié)議
    (someContainer: C1, _ anotherContainer: C2) -> Bool {

    // do something
}

// 3.0
func allItemsMatch<
    C1: Container, C2: Container>
    (_ someContainer: C1, _ anotherContainer: C2) -> Bool
    // where 語句的位置發(fā)成了變化, 被放在了尖括號外部
    where C1.ItemType == C2.ItemType, C1.ItemType: Equatable {
        
    // do something
}
*更新了逃逸閉包的內(nèi)容, 現(xiàn)在它默認是非逃逸閉包了

參考上面的變化

*更新了基礎章節(jié)中的 optional 綁定以及語句章節(jié)中 while 語句的內(nèi)容, 現(xiàn)在 if, while 和 guard 語句用一個逗號分割的列表來替代了 where 語句, 例如:
// 3.0以前
if let firstNumber = Int("4") {
    if let secondNumber = Int("42") {
        if firstNumber < secondNumber && secondNumber < 100 {
            print("\(firstNumber) < \(secondNumber) < 100")
        }
    }
}
// Prints "4 < 42 < 100"

// 3.0
if let firstNumber = Int("4"), let secondNumber = Int("42"), firstNumber < secondNumber && secondNumber < 100 {
    print("\(firstNumber) < \(secondNumber) < 100")
}
// Prints "4 < 42 < 100"

*在流程控制中的 switch 中的 case 中添加了多種模式匹配.

其實就是說一個case分支現(xiàn)在可以寫多個模式匹配了, 如果用原來的寫法的話, 就應該要用 fallthrough來寫2個 case.

switch control expression {
case pattern 1:
    statements
case pattern 2 where condition:
    statements
case pattern 3 where condition,   <-- 這里
     pattern 4 where condition:
    statements
default:
    statements
}
*更新了關于函數(shù)類型的內(nèi)容, 現(xiàn)在函數(shù)參數(shù)標簽不再屬于函數(shù)類型的一部分了

直接看看官方的例子:

func someFunction(left: Int, right: Int) {}
func anotherFunction(left: Int, right: Int) {}
func functionWithDifferentLabels(top: Int, bottom: Int) {}
 
var f = someFunction // 現(xiàn)在 f 的類型是 (Int, Int) -> Void, 而不是 (left: Int, right: Int) -> Void 了.
f = anotherFunction              // OK
f = functionWithDifferentLabels  // OK
 
func functionWithDifferentArgumentTypes(left: Int, right: String) {}
func functionWithDifferentNumberOfArguments(left: Int, right: Int, top: Int) {}
 
f = functionWithDifferentArgumentTypes     // Error
f = functionWithDifferentNumberOfArguments // Error
*在協(xié)議章節(jié)更新了協(xié)議組合的內(nèi)容, 以及類型章節(jié)中協(xié)議組合使用了 Protocol1 & Protocol2的新用法
// 3.0以前
protocol Named {
    var name: String { get }
}
protocol Aged {
    var age: Int { get }
}
struct Person: Named, Aged {
    var name: String
    var age: Int
}
func wishHappyBirthday(celebrator: protocol<Named, Aged>) { // <-- 區(qū)別
    print("Happy birthday \(celebrator.name) - you're \(celebrator.age)!")
}
let birthdayPerson = Person(name: "Malcolm", age: 21)
wishHappyBirthday(birthdayPerson)

// 3.0

protocol Named {
    var name: String { get }
}
protocol Aged {
    var age: Int { get }
}
struct Person: Named, Aged {
    var name: String
    var age: Int
}
func wishHappyBirthday(to celebrator: Named & Aged) { // <-- 區(qū)別
    print("Happy birthday, \(celebrator.name), you're \(celebrator.age)!")
}
let birthdayPerson = Person(name: "Malcolm", age: 21)
wishHappyBirthday(to: birthdayPerson)
*在動態(tài)類型描述的內(nèi)容, 現(xiàn)在使用新的 type(of:)語法來獲取動態(tài)類型描述

typeof 的用法官方給了例子, 其實也就是相當于給了個全局的函數(shù), 返回一個 Class 對象.

class SomeBaseClass {
    class func printClassName() {
        print("SomeBaseClass")
    }
}
class SomeSubClass: SomeBaseClass {
    override class func printClassName() {
        print("SomeSubClass")
    }
}
let someInstance: SomeBaseClass = SomeSubClass()
// someInstance 在編譯期的時候有一個靜態(tài)的類型-- SomeBaseClass, 在 runtime 的時候有一個動態(tài)的類型--SomeSubClass
type(of: someInstance).printClassName()
// 打印出"SomeSubClass"
*更新了航控制語句小節(jié)中使用#sourceLocation(file:line:)語法的內(nèi)容

根據(jù)描述應該是可以自己制定代碼的文件名和行數(shù), 一般作為診斷和 debug 來使用.

*更新了函數(shù)永不返回中使用新的 Never 類型

swift 定義了一種 Never 的類型, 它指示了函數(shù)或者方法不會返回到調(diào)用方

*更新了 In-Out 參數(shù)小節(jié)中的內(nèi)容--只有非逃逸閉包可以捕獲 in-out 參數(shù)
*更新了默認參數(shù)值小節(jié)中關于默認參數(shù)的內(nèi)容, 現(xiàn)在他們不能在函數(shù)調(diào)用中重新訂閱了
*更新了屬性章節(jié)中屬性參數(shù)使用冒號

主要是配合 @available來使用, 如下面的例子, @available后面接 typealias(只作用一個, 有多個 typealias 只會作用于下面第一個) 導致 MyProtocol在后續(xù)發(fā)布后并不能真正地 alias 為MyRenamedProtocol, 只是為編譯器提供了提示的信息, 報錯會有 fix-it 出現(xiàn).

// 第一次版本發(fā)布
protocol MyProtocol {
    // protocol definition
}
// 后續(xù)發(fā)布版本重新命名了MyProtocol
protocol MyRenamedProtocol {
    // protocol definition
}
 
@available(*, unavailable, renamed: "MyRenamedProtocol")
typealias MyProtocol = MyRenamedProtocol

enum SomeEnum: MyProtocol {  // <-- 這里報錯, 并出現(xiàn) fix-it, 要求變?yōu)镸yRenamedProtocol, 
//如果MyRenamedProtocol拼寫錯誤如寫成MyRenamedProtocolTest, fix-it 的結(jié)果也會編程MyRenamedProtocolTest
    
}
*在重新拋出函數(shù)和方法小節(jié)中增加了關于在 rethrowing 函數(shù)的catch block內(nèi)部錯誤的內(nèi)容.

直白的說, 增加了在標注為 rethrows 的函數(shù)/方法中, 只有出現(xiàn)一個異常語句, 基本可以理解為只能出現(xiàn)一個 try.

enum SomeError:Error {
    case error
}

enum AnotherError:Error {
    case error
}


func alwaysThrows() throws {
    throw SomeError.error
}
func someFunction(callback: () throws -> Void) rethrows {
    do {
        try callback()
//        try alwaysThrows()  // 去掉注釋就報錯
    } catch SomeError.error{
        throw AnotherError.error
    }catch AnotherError.error{
        
    }
}
*增加了#selector 的objc屬性的 getter 和 setter 方法描述.

之前的版本都是用字符串來尋找 selector, 沒有提示, 很容易出錯, 而且不報錯, 比較坑爹, 3.0增加了類似原來@selector 的形式, 而且更加好用了.

class SomeClass: NSObject {
    let property: String
    @objc(doSomethingWithInt:)
    func doSomething(_ x: Int) {}
    
    init(property: String) {
        self.property = property
    }
}
let selectorForMethod = #selector(SomeClass.doSomething(_:))
let selectorForPropertyGetter = #selector(getter: SomeClass.property)
*增加了類型別名聲明小節(jié)中, 關于泛型的別名和在協(xié)議中使用別名的內(nèi)容

類型別名可以使用泛型參數(shù)來給定一個已有的泛型起名,例如:

typealias StringDictionary<Value> = Dictionary<String, Value>
 
// 下面兩個 dictionary 都是一樣的類型
var dictionary1: StringDictionary<Int> = [:]
var dictionary2: Dictionary<String, Int> = [:]

類型別名用泛型參數(shù)聲明了時候, 參數(shù)是可以加限制的, 例如:

typealias DictionaryOfInts<Key: Hashable> = Dictionary<Key, Int>

在協(xié)議內(nèi)部, 類型別名可以提供一個更加簡短和方便的名字, 例如:

protocol Sequence {
    associatedtype Iterator: IteratorProtocol
    typealias Element = Iterator.Element
}
 
func sum<T: Sequence>(_ sequence: T) -> Int where T.Element == Int {
    // ...
}
*更新了函數(shù)類型小節(jié)的內(nèi)容, 現(xiàn)在參數(shù)的圓括號是必須的了

主要是因為元組的原因, ((Int, Int)) -> Void(Int, Int) -> Void還是有很明顯的區(qū)別的.

*更新了屬性章節(jié)中, @IBAction, @IBOutlet 和 @NSManaged會附帶@objc的內(nèi)容

也就是說只要加上了上面三種屬性的其中之一, 就會自動加上 @objc屬性.

*在屬性章節(jié)中, 增加了 @GKInspectable 的內(nèi)容

文檔的描述如下:

Apply this attribute to expose a custom GameplayKit component property to the SpriteKit editor UI.
應用此屬性來暴露一個自定義的 GameplayKit 組件屬性到 SpriteKit 編輯器的 UI 上

說實話, 沒有玩過 GameplayKit, 只能硬翻了 :p, 字面上的意思也還好理解 GK=gamekit, inspectable, 可檢測到的

*更新了可選協(xié)議要求小節(jié)的內(nèi)容, 使得這部分代碼只用于 objc 變得更加清晰了
// 3.0以前
@objc protocol CounterDataSource {
    optional func incrementForCount(count: Int) -> Int
    optional var fixedIncrement: Int { get }
}

// 3.0
@objc protocol CounterDataSource {
    @objc optional func increment(forCount count: Int) -> Int
    @objc optional var fixedIncrement: Int { get }
}
*移除了函數(shù)聲明小節(jié)中, 在函數(shù)參數(shù)中顯式使用 let 的內(nèi)容

以前記得是如果整個函數(shù)沒有對參數(shù)進行修改, 就要在參數(shù)中加上 let 來修飾, 看起來這個設定被丟棄了.

*移除了語句章節(jié)中, Boolean 協(xié)議的內(nèi)容, 現(xiàn)在這個協(xié)議已經(jīng)從 Swift 標準庫中移除了
*糾正了聲明屬性小節(jié)中對 @NSApplicationMain的描述

Swift 3.0.1 變動

*更新了 ARC 章節(jié)中, weak 和 unowned 引用的內(nèi)容

weak和 unowned 因為已經(jīng)找不到2.2的描述, 看了最新的描述, 和之前的理解沒有明顯的差距, 貌似都是增加了一個 NOTE,
weak 的 NOTE 是:

Property observers aren’t called when ARC sets a weak reference to nil.

weak 屬性被自動設置為 nil 的時候不會觸發(fā)屬性觀察方法

之前自動設置為 nil 的時候是會觸發(fā)屬性監(jiān)聽的, 新版本改為不觸發(fā)了.

小 Tip: 如果要驗證老的邏輯, 可以在Build Settings里面Use Legacy Swift Language Version 設置為 Yes

unowned 的 NOTE 是:

The examples above show how to use safe unowned references. Swift also provides unsafe unowned references for cases where you need to disable runtime safety checks—for example, for performance reasons. As with all unsafe operations, you take on the responsiblity for checking that code for safety.

You indicate an unsafe unowned reference by writing unowned(unsafe). If you try to access an unsafe unowned reference after the instance that it refers to is deallocated, your program will try to access the memory location where the instance used to be, which is an unsafe operation.

上面的例子展示了如何安全地使用 unowned 引用. Swift 還提供了非安全的 unowned 引用, 來應付不需要在 runtime 時期做安全性檢查的場景, 例如為了提高性能. 如其它的非安全操作, 你需要自己為代碼安全性負責.

用unowned(unsafe)來標記非安全的 unowned 引用. 如果你嘗試訪問一個非安全引用的實例, 而且它已經(jīng)被析構(gòu)了, 進程會訪問這個實例之前存在的內(nèi)存空間, 這是個不安全的操作.

這個 NOTE 說明 Swift 提供了一種新的, 高性能的引用方式, 只是要付出安全性的代價.

*在聲明修飾符章節(jié)中增加了unowned, unowned(safe), 和 unowned(unsafe)的說明

上面已經(jīng)有部分說明了
unowned(safe)unowned的顯式寫法, 也就是說, unowned 默認就是unowned(safe).
unowned(unsafe)unowned(safe)的區(qū)別主要是, unowned(safe)在訪問一個已經(jīng)析構(gòu)的對象, 會直接觸發(fā) runtime error, 而unowned(unsafe) 則會去訪問這個實例曾經(jīng)存在的地址, 其作用則是未知的.

*在Any 和 AnyObject 類型轉(zhuǎn)換小節(jié)中增加了關于當值是被期望是 Any 的時候使用 optional 的小記

The Any type represents values of any type, including optional types. Swift gives you a warning if you use an optional value where a value of type Any is expected. If you really do need to use an optional value as an Any value, you can use the as operator to explicitly cast the optional to Any, as shown below.

let optionalNumber: Int? = 3
things.append(optionalNumber)        // Warning
things.append(optionalNumber as Any) // No warning

Any 類型帶了了所有的類型, 包括 Optional 類型. 當你在需要 Any 類型的場合使用了 Optional 類型, 編譯器會給你一個警告. 如果你確實需要把 Optional 的值當做 Any 類型使用, 可以用as 操作符把它顯式轉(zhuǎn)化為Any, 如代碼所示.

*在 Expressions 章節(jié)中拆分了圓括號表述和元組表述

Swift 3.1 變動

*增加了包含 Where 從句泛型的拓展小節(jié)

現(xiàn)在拓展中的泛型也可以加 where 從句了, 來限定拓展的內(nèi)容:

extension Stack where Element: Equatable {
    func isTop(_ item: Element) -> Bool {
        guard let topItem = items.last else {
            return false
        }
        return topItem == item
    }
}

如果Stack 指定了沒有實現(xiàn)Equatable的類型, 在使用 isTop 的時候會報錯.

struct NotEquatable { }
var notEquatableStack = Stack<NotEquatable>()
let notEquatableValue = NotEquatable()
notEquatableStack.push(notEquatableValue)
notEquatableStack.isTop(notEquatableValue)  // Error
*增加了聲明屬性小節(jié)中關于 Swift 版本的available屬性的內(nèi)容

針對 Swift 版本也可以使用 @available 了, 之前都是平臺和系統(tǒng)版本之類的.
@available(swift version-number)

*更新了條件編譯塊小節(jié)中 Swift 版本數(shù)字的內(nèi)容, 現(xiàn)在patch 版本號也允許使用了

可以理解為之前的條件編譯也加上了 Swift 版本的控制.

*更新了函數(shù)類型小節(jié)的內(nèi)容. 現(xiàn)在 Swift 區(qū)分多參數(shù)函數(shù)和只有一個元組類型參數(shù)的函數(shù)了

直接上例子吧:

// 3.1以前:
func methodForTuple(t:(a: Int, b: Int, c: Int)){}    
func methodForMulti(a: Int, b : Int, c: Int){}

var tupleFunction = methodForTuple
tupleFunction = methodForMulti // 沒有報錯, 說明編譯器認為這兩個個函數(shù)是一個類型的

// 3.1之后就會報錯了, 因為暫時沒有更新 Xcode到最新版, 所以沒有驗證這一點

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市固以,隨后出現(xiàn)的幾起案子闲询,更是在濱河造成了極大的恐慌驳遵,老刑警劉巖延塑,帶你破解...
    沈念sama閱讀 212,599評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件羞福,死亡現(xiàn)場離奇詭異逞敷,居然都是意外死亡狂秦,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,629評論 3 385
  • 文/潘曉璐 我一進店門推捐,熙熙樓的掌柜王于貴愁眉苦臉地迎上來裂问,“玉大人,你說我怎么就攤上這事牛柒】安荆” “怎么了?”我有些...
    開封第一講書人閱讀 158,084評論 0 348
  • 文/不壞的土叔 我叫張陵皮壁,是天一觀的道長戴甩。 經(jīng)常有香客問我,道長闪彼,這世上最難降的妖魔是什么甜孤? 我笑而不...
    開封第一講書人閱讀 56,708評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮畏腕,結(jié)果婚禮上缴川,老公的妹妹穿的比我還像新娘。我一直安慰自己描馅,他們只是感情好把夸,可當我...
    茶點故事閱讀 65,813評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著铭污,像睡著了一般恋日。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上嘹狞,一...
    開封第一講書人閱讀 50,021評論 1 291
  • 那天岂膳,我揣著相機與錄音,去河邊找鬼磅网。 笑死谈截,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播簸喂,決...
    沈念sama閱讀 39,120評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼毙死,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了喻鳄?” 一聲冷哼從身側(cè)響起扼倘,我...
    開封第一講書人閱讀 37,866評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎除呵,沒想到半個月后再菊,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,308評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡竿奏,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,633評論 2 327
  • 正文 我和宋清朗相戀三年袄简,在試婚紗的時候發(fā)現(xiàn)自己被綠了腥放。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片泛啸。...
    茶點故事閱讀 38,768評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖秃症,靈堂內(nèi)的尸體忽然破棺而出候址,到底是詐尸還是另有隱情,我是刑警寧澤种柑,帶...
    沈念sama閱讀 34,461評論 4 333
  • 正文 年R本政府宣布岗仑,位于F島的核電站,受9級特大地震影響聚请,放射性物質(zhì)發(fā)生泄漏荠雕。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,094評論 3 317
  • 文/蒙蒙 一驶赏、第九天 我趴在偏房一處隱蔽的房頂上張望炸卑。 院中可真熱鬧,春花似錦煤傍、人聲如沸盖文。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,850評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽五续。三九已至,卻和暖如春龄恋,著一層夾襖步出監(jiān)牢的瞬間疙驾,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,082評論 1 267
  • 我被黑心中介騙來泰國打工郭毕, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留荆萤,地道東北人。 一個月前我還...
    沈念sama閱讀 46,571評論 2 362
  • 正文 我出身青樓,卻偏偏與公主長得像链韭,于是被迫代替她去往敵國和親偏竟。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,666評論 2 350

推薦閱讀更多精彩內(nèi)容

  • Hello Word 在屏幕上打印“Hello, world”敞峭,可以用一行代碼實現(xiàn): 你不需要為了輸入輸出或者字符...
    restkuan閱讀 3,171評論 0 6
  • Swift 介紹 簡介 Swift 語言由蘋果公司在 2014 年推出踊谋,用來撰寫 OS X 和 iOS 應用程序 ...
    大L君閱讀 3,201評論 3 25
  • importUIKit classViewController:UITabBarController{ enumD...
    明哥_Young閱讀 3,788評論 1 10
  • 當你難過了,你就跑吧旋讹。 當你失望了殖蚕,你就跑吧。 當左邊的聲音罵你沉迹,你就往前跑吧睦疫。 當右邊的聲音拉你,你就往前跑吧鞭呕。...
    米妮安M閱讀 148評論 0 0
  • Content-Type指示響應的內(nèi)容蛤育,這里是text/html表示HTML網(wǎng)頁。請注意葫松,瀏覽器就是依靠Conte...
    愛吃葡萄冰的鯨閱讀 300評論 0 0