有一段時間沒有寫 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到最新版, 所以沒有驗證這一點