1.前言:
Swift
包含了 C
和 Objective-C
上所有基礎(chǔ)數(shù)據(jù)類型状植,Int
表示整型值优炬; Double
和 Float
表示浮點(diǎn)型值; Bool
是布爾型值境蔼;String
是文本型數(shù)據(jù)。 Swift
還提供了三個(gè)基本的集合類型伺通,Array
箍土,Set
和 Dictionary
。
在 Swift
中罐监,廣泛的使用著值不可變的變量吴藻,它們就是常量。而且比 C
語言的常量更強(qiáng)大弓柱。在 Swift
中沟堡,如果你要處理的值不需要改變侧但,那使用常量可以讓你的代碼更加安全并且更清晰地表達(dá)你的意圖。
Swift
是一門類型安全
的語言航罗,可選類型
就是一個(gè)很好的例子禀横。
2.字符串插值
Swift
用字符串插值(string interpolation
)的方式把常量名或者變量名當(dāng)做占位符加入到長字符串中,Swift
會用當(dāng)前常量或變量的值替換這些占位符粥血。
var friendlyWelcome = "朋友你好柏锄!"
print("The current value of friendlyWelcome is \(friendlyWelcome)")
// 輸出 "The current value of friendlyWelcome is Bonjour!
-
類型推斷
let possibleNumber = "123"
let convertedNumber = Int(possibleNumber)
// convertedNumber 被推測為類型 "Int?", 或者類型 "optional Int"
如果possibleNumber
是"asdas复亏,那么convertedNumber
就是nil
4.nil
你可以給可選變量賦值為nil
來表示它沒有值:
var surveyAnswer: String?
// surveyAnswer 被自動設(shè)置為 nil
Swift
的 nil
和 Objective-C
中的 nil
并不一樣趾娃。在 Objective-C
中,nil
是一個(gè)指向不存在對象的指針缔御。在 Swift
中抬闷,nil
不是指針——它是一個(gè)確定的值,用來表示值缺失
耕突。任何類型的可選狀態(tài)都可以被設(shè)置為 nil
笤成,不只是對象類型。
5.隱式解析可選類型
把想要用作可選的類型的后面的問號(String?
)改成感嘆號(String!
)來聲明一個(gè)隱式解析可選類型有勾。
可以把隱式解析可選類型當(dāng)做一個(gè)可以自動解析的可選類型疹启。你要做的只是聲明的時(shí)候把感嘆號放到類型的結(jié)尾,而不是每次取值的可選名字的結(jié)尾蔼卡。
6.錯(cuò)誤處理
你可以使用 錯(cuò)誤處理(error handling
) 來應(yīng)對程序執(zhí)行中可能會遇到的錯(cuò)誤條件喊崖。
1)函數(shù)throws
7.集合類型
Swift
語言提供Arrays
、Sets
和Dictionaries
三種基本的集合類型用來存儲集合數(shù)據(jù)雇逞。數(shù)組(Arrays
)是有序數(shù)據(jù)的集荤懂。集合(Sets
)是無序無重復(fù)數(shù)據(jù)的集。字典(Dictionaries
)是無序的鍵值對的集塘砸。
Swift
的Arrays
节仿、Sets
和Dictionaries
類型被實(shí)現(xiàn)為泛型
集合。
在我們不需要改變集合的時(shí)候創(chuàng)建不可變集合是很好的實(shí)踐掉蔬。如此 Swift
編譯器可以優(yōu)化我們創(chuàng)建的集合廊宪。 Swift
的Array
類型被橋接到Foundation
中的NSArray
類
1)數(shù)組
通過兩個(gè)數(shù)組相加創(chuàng)建一個(gè)數(shù)組
var threeDoubles = [Double](repeating: 0.0, count: 3)
var anotherThreeDoubles = [Double](repeatElement(0.125, count: 3))
var sixDoubles = threeDoubles + anotherThreeDoubles
可以使用數(shù)組的只讀屬性count
來獲取數(shù)組中的數(shù)據(jù)項(xiàng)數(shù)量:
2)集合(Sets)
集合(Set
)用來存儲相同類型并且沒有確定順序的值。當(dāng)集合元素順序不重要
時(shí)或者希望確保每個(gè)元素只出現(xiàn)一次
時(shí)可以使用集合而不是數(shù)組女轿。
Swift
的Set
類型被橋接到Foundation
中的NSSet
類箭启。
集合類型的哈希值
一個(gè)類型為了存儲在集合
中,該類型必須是可哈向燃#化
的
一個(gè)類型為了存儲在集合中傅寡,該類型必須是可哈希化
的--也就是說,該類型必須提供一個(gè)方法來計(jì)算它的哈希值荐操。一個(gè)哈希值是Int
類型的芜抒,相等的對象哈希值必須相同,比如a==b
,因此必須a.hashValue == b.hashValue
托启。
Swift
的所有基本類型(比如String,Int,Double和Bool
)默認(rèn)都是可哈险梗化
的,可以作為集合的值的類型或者字典的鍵的類型驾中。沒有關(guān)聯(lián)值的枚舉成員值(在枚舉有講述)默認(rèn)也是可哈习埃化的。
Swift
中的Set
類型被寫為Set<Element>
肩民,這里的Element
表示Set
中允許存儲的類型唠亚,和數(shù)組不同的是,集合沒有等價(jià)的簡化形式持痰。
*注意:集合要聯(lián)想起我們高中數(shù)學(xué)的集合灶搜。
使用intersect(_:)
方法根據(jù)兩個(gè)集合中都包含的值創(chuàng)建的一個(gè)新的集合。
使用exclusiveOr(_:)
方法根據(jù)在一個(gè)集合中但不在兩個(gè)集合中的值創(chuàng)建一個(gè)新的集合工窍。
使用union(_:)
方法根據(jù)兩個(gè)集合的值創(chuàng)建一個(gè)新的集合割卖。
使用subtract(_:)
方法根據(jù)不在該集合中的值創(chuàng)建一個(gè)新的集合。
3)字典
Swift
的Dictionary
類型被橋接到Foundation
的NSDictionary
類患雏。
字典是一種存儲多個(gè)相同類型的值的容器鹏溯。每個(gè)值(value
)都關(guān)聯(lián)唯一的鍵(key
),鍵作為字典中的這個(gè)值數(shù)據(jù)的標(biāo)識符淹仑。和數(shù)組中的數(shù)據(jù)項(xiàng)不同丙挽,字典中的數(shù)據(jù)項(xiàng)并沒有具體順序。我們在需要通過標(biāo)識符(鍵)訪問數(shù)據(jù)的時(shí)候使用字典匀借,這種方法很大程度上和我們在現(xiàn)實(shí)世界中使用字典查字義的方法一樣颜阐。
Swift
的字典使用Dictionary<Key, Value>
定義,其中Key
是字典中鍵的數(shù)據(jù)類型吓肋,Value
是字典中對應(yīng)于這些鍵所存儲值的數(shù)據(jù)類型凳怨。
創(chuàng)建一個(gè)空字典
var namesOfIntegers = [Int: String]()
// namesOfIntegers 是一個(gè)空的 [Int: String] 字典
8.控制流
提前退出
像if
語句一樣,guard
的執(zhí)行取決于一個(gè)表達(dá)式的布爾值是鬼。我們可以使用guard
語句來要求條件必須為真時(shí)肤舞,以執(zhí)行guard
語句后的代碼。不同于if
語句均蜜,一個(gè)guard
語句總是有一個(gè)else
從句萨赁,如果條件不為真則執(zhí)行else
從句中的代碼。
9.檢測 API 可用性
if #available(iOS 10, macOS 10.12, *) {
// 在 iOS 使用 iOS 10 的 API, 在 macOS 使用 macOS 10.12 的 API
} else {
// 使用先前版本的 iOS 和 macOS 的 API
}
10.函數(shù)
參數(shù)標(biāo)簽 (Specifying Argument Labels
)
可以在函數(shù)名稱前指定它的參數(shù)標(biāo)簽兆龙,中間以空格分隔:
func someFunction(argumentLabel parameterName: Int) {
// In the function body, parameterName refers to the argument value
// for that parameter.
}
func greet(person: String, from hometown: String) -> String {
return "Hello \(person)! Glad you could visit from \(hometown)."
}
print(greet(person: "Bill", from: "Cupertino"))
// Prints "Hello Bill! Glad you could visit from Cupertino."
*注意:這里的from 就是參數(shù)hometown的標(biāo)簽
參數(shù)標(biāo)簽的使用能夠讓一個(gè)函數(shù)在調(diào)用時(shí)更有表達(dá)力,更類似自然語言,并且仍保持了函數(shù)內(nèi)部的可讀性以及清晰的意圖紫皇。
忽略參數(shù)標(biāo)簽(Omitting Argument Labels
)
如果不希望為某個(gè)參數(shù)添加一個(gè)標(biāo)簽慰安,可以使用一個(gè)下劃線(_
)來代替一個(gè)明確的參數(shù)標(biāo)簽。
func someFunction(_ firstParameterName: Int, secondParameterName: Int) {
// In the function body, firstParameterName and secondParameterName
// refer to the argument values for the first and second parameters.
}
someFunction(1, secondParameterName: 2)
可變參數(shù) (Variadic Parameters
)
一個(gè)可變參數(shù)(variadic parameter
)可以接受零個(gè)或多個(gè)值聪铺。通過在變量類型名后面加入(...
)的方式來定義可變參數(shù)
一個(gè)函數(shù)最多只能擁有一個(gè)可變參數(shù)化焕。
輸入輸出參數(shù)(In-Out Parameters
)
函數(shù)參數(shù)默認(rèn)是常量。
只能傳遞變量給輸入輸出參數(shù)铃剔。你不能傳入常量
或者字面量
(literal value
)撒桨,因?yàn)檫@些量是不能被修改的。當(dāng)傳入的參數(shù)作為輸入輸出參數(shù)時(shí)键兜,需要在參數(shù)名前加 &
符凤类,表示這個(gè)值可以被函數(shù)修改。
eg:
函數(shù)類型 (Function Types
)
每個(gè)函數(shù)都有種特定的函數(shù)類型普气,函數(shù)的類型由函數(shù)的參數(shù)類型
和返回類型
組成谜疤。
func eschop(_ a: Strinfg, _b: Int) -> String {
// func body
}
函數(shù)類型為:(String, Int) -> String
嵌套函數(shù)
可以把函數(shù)定義在別的函數(shù)體中,稱作 嵌套函數(shù)(nested functions
)
默認(rèn)情況下现诀,嵌套函數(shù)
是對外界不可見的夷磕,但是可以被它們的外圍函數(shù)
(enclosing function
)調(diào)用。
func chooseStepFunction(backward: Bool) -> (Int) -> Int {
func stepForward(input: Int) -> Int { return input + 1 }
func stepBackward(input: Int) -> Int { return input - 1 }
return backward ? stepBackward : stepForward
}
var currentValue = -4
let moveNearerToZero = chooseStepFunction(backward: currentValue > 0)
// moveNearerToZero now refers to the nested stepForward() function
while currentValue != 0 {
print("\(currentValue)... ")
currentValue = moveNearerToZero(currentValue)
}
print("zero!")
// -4...
// -3...
// -2...
// -1...
// zero!
11.閉包(Closures
)
閉包
是自包含
的函數(shù)代碼塊
仔沿,可以在代碼中被傳遞
和使用
坐桩。Swift
中的閉包
與 C
和 Objective-C
中的代碼塊(blocks
)以及其他一些編程語言中的匿名函數(shù)
比較相似。
閉包
可以捕獲和存儲其所在上下文
中任意常量
和變量
的引用封锉。閉合
绵跷、包裹
常量和變量,所謂閉包
也烘浦。Swift
會為你管理在捕獲過程中涉及到的所有內(nèi)存操作抖坪。
捕獲(capturing):閉包可以在其被定義的上下文中捕獲常量或變量。即使定義這些常量和變量的原作用域已經(jīng)不存在闷叉,閉包仍然可以在閉包函數(shù)體內(nèi)引用和修改這些值擦俐。
Swift 中,可以捕獲值的閉包的最簡單形式是嵌套函數(shù)握侧,也就是定義在其他函數(shù)的函數(shù)體內(nèi)的函數(shù)蚯瞧。嵌套函數(shù)可以捕獲其外部函數(shù)所有的參數(shù)以及定義的常量和變量。
全局和嵌套函數(shù)實(shí)際上也是特殊的閉包:
閉包采取如下三種形式之一:
·全局函數(shù)是一個(gè)有名字但不會捕獲
任何值的閉包
·嵌套函數(shù)是一個(gè)有名字并可以捕獲
其封閉函數(shù)域內(nèi)值的閉包
·閉包表達(dá)式是一個(gè)利用輕量級語法所寫的可以捕獲
其上下文中變量或常量值的匿名閉包
如果你將閉包
賦值給一個(gè)類實(shí)例的屬性品擎,并且該閉包通過訪問該實(shí)例或其成員而捕獲
了該實(shí)例埋合,你將在閉包和該實(shí)例間創(chuàng)建一個(gè)循環(huán)強(qiáng)引用。Swift 使用捕獲列表
來打破這種循環(huán)強(qiáng)引用萄传。
Swift
的閉包表達(dá)式擁有簡潔的風(fēng)格甚颂,并鼓勵在常見場景中進(jìn)行語法優(yōu)化,主要優(yōu)化如下:
1)利用上下文推斷參數(shù)和返回值類型
2)隱式返回單表達(dá)式閉包,即單表達(dá)式閉包可以省略 return
關(guān)鍵字
3)參數(shù)名稱縮寫
4)尾隨(Trailing
)閉包語法
閉包表達(dá)式(Closure Expressions
)
嵌套函數(shù)是一個(gè)在較復(fù)雜函數(shù)中方便進(jìn)行命名和定義自包含代碼模塊的方式振诬。
當(dāng)然蹭睡,有時(shí)候編寫小巧的沒有完整定義和命名的類函數(shù)結(jié)構(gòu)也是很有用處的,尤其是在你處理一些函數(shù)并需要將另外一些函數(shù)作為該函數(shù)的參數(shù)時(shí)赶么。
閉包表達(dá)式
是一種利用簡潔語法構(gòu)建內(nèi)聯(lián)閉包的方式肩豁。
閉包表達(dá)式提供了一些語法優(yōu)化,使得撰寫閉包變得簡單明了辫呻。
sorted(by:)
方法接受一個(gè)閉包清钥,該閉包函數(shù)需要傳入與數(shù)組元素類型相同的兩個(gè)值,并返回一個(gè)布爾類型值來表明當(dāng)排序結(jié)束后傳入的第一個(gè)參數(shù)排在第二個(gè)參數(shù)前面還是后面放闺。如果第一個(gè)參數(shù)值出現(xiàn)在第二個(gè)參數(shù)值前面祟昭,排序閉包函數(shù)需要返回true
,反之返回false
雄人。
利用閉包表達(dá)式語法可以更好地構(gòu)造一個(gè)內(nèi)聯(lián)排序閉包
从橘。
閉包表達(dá)式語法(Closure Expression Syntax
)
閉包表達(dá)式語法有如下的一般形式:
閉包表達(dá)式的參數(shù)可以是inout
參數(shù),但不能設(shè)定默認(rèn)值础钠。
也可以使用具名的可變參數(shù).元組也可以作為參數(shù)和返回值恰力。
內(nèi)聯(lián)閉包參數(shù)和返回值類型聲明與 backward(::) 函數(shù)類型聲明相同。在內(nèi)聯(lián)閉包表達(dá)式中旗吁,函數(shù)和返回值類型都寫在大括號內(nèi)踩萎,而不是大括號外。
reversedNames = names.sorted(by: { s1, s2 in return s1 > s2 } )
根據(jù)上下文推斷類型(Inferring Type From Context
)
通過內(nèi)聯(lián)閉包表達(dá)式
構(gòu)造的閉包
作為參數(shù)傳遞給函數(shù)或方法時(shí)很钓,總是能夠推斷出閉包
的參數(shù)和返回值類型香府。
單表達(dá)式閉包隱式返回(Implicit Returns From Single-Expression Closures
)
單行表達(dá)式閉包可以通過省略 return 關(guān)鍵字來隱式返回單行表達(dá)式的結(jié)果,如上版本的例子可以改寫為:
reversedNames = names.sorted(by: { s1, s2 in s1 > s2 } )
參數(shù)名稱縮寫(Shorthand Argument Names
)
reversedNames = names.sorted(by: { $0 > $1 } )
在這個(gè)例子中码倦,$0和$1表示閉包中第一個(gè)和第二個(gè) String 類型的參數(shù)企孩。
運(yùn)算符方法(Operator Methods
)
Swift
的 String
類型定義了關(guān)于大于號(>
)的字符串實(shí)現(xiàn),其作為一個(gè)函數(shù)接受兩個(gè) String
類型的參數(shù)并返回 Bool
類型的值袁稽。而這正好與 sorted(by:)
方法的參數(shù)需要的函數(shù)類型相符合勿璃。因此,你可以簡單地傳遞一個(gè)大于號推汽,Swift
可以自動推斷出你想使用大于號的字符串函數(shù)實(shí)現(xiàn):
reversedNames = names.sorted(by: >)
尾隨閉包(Trailing Closures
)
如果你需要將一個(gè)很長的閉包表達(dá)式
作為最后一個(gè)參數(shù)傳遞給函數(shù)补疑,可以使用尾隨閉包
來增強(qiáng)函數(shù)的可讀性。
尾隨閉包是一個(gè)書寫在函數(shù)括號之后的閉包表達(dá)式歹撒,函數(shù)支持將其作為最后一個(gè)參數(shù)調(diào)用莲组。在使用尾隨閉包時(shí),你不用寫出它的參數(shù)標(biāo)簽:
func someFunctionThatTakesAClosure(closure: () -> Void) {
// 函數(shù)體部分
}
// 以下是不使用尾隨閉包進(jìn)行函數(shù)調(diào)用
someFunctionThatTakesAClosure(closure: {
// 閉包主體部分
})
// 以下是使用尾隨閉包進(jìn)行函數(shù)調(diào)用
someFunctionThatTakesAClosure() {
// 閉包主體部分
}
reversedNames = names.sorted() { $0 > $1 } // 方法參數(shù)的字符串排序閉包可以改寫為:
reversedNames = names.sorted { $0 > $1 } // 如果閉包表達(dá)式是函數(shù)或方法的唯一參數(shù)暖夭,則當(dāng)你使用尾隨閉包時(shí)锹杈,你甚至可以把 () 省略掉
當(dāng)閉包非常長以至于不能在一行中進(jìn)行書寫時(shí)撵孤,尾隨閉包變得非常有用。
舉例來說嬉橙,Swift
的 Array
類型有一個(gè) map(_:)
方法早直,這個(gè)方法獲取一個(gè)閉包表達(dá)式作為其唯一參數(shù)。該閉包函數(shù)會為數(shù)組中的每一個(gè)元素調(diào)用一次市框,并返回該元素所映射的值。具體的映射方式和返回值類型由閉包來指定糕韧。
閉包是引用類型(Closures Are Reference Types)
無論你將函數(shù)或閉包賦值給一個(gè)常量還是變量枫振,你實(shí)際上都是將常量或變量的值設(shè)置為對應(yīng)函數(shù)或閉包的引用。
逃逸閉包(Escaping Closures)
當(dāng)一個(gè)閉包作為參數(shù)傳到一個(gè)函數(shù)中萤彩,但是這個(gè)閉包在函數(shù)返回之后才被執(zhí)行粪滤,我們稱該閉包從函數(shù)中逃逸
。
當(dāng)你定義接受閉包作為參數(shù)的函數(shù)時(shí)雀扶,你可以在參數(shù)名之前標(biāo)注 @escaping
杖小,用來指明這個(gè)閉包是允許“逃逸”出這個(gè)函數(shù)的。
一種能使閉包“逃逸”
出函數(shù)的方法是愚墓,將這個(gè)閉包保存在一個(gè)函數(shù)外部定義的變量中予权。舉個(gè)例子,很多啟動異步操作的函數(shù)接受一個(gè)閉包參數(shù)作為completion handler
浪册。這類函數(shù)會在異步操作開始之后立刻返回扫腺,但是閉包直到異步操作結(jié)束后才會被調(diào)用。在這種情況下村象,閉包需要“逃逸”出函數(shù)笆环,因?yàn)殚]包需要在函數(shù)返回之后被調(diào)用。例如:
var completionHandlers: [() -> Void] = []
func someFunctionWithEscapingClosure(completionHandler: @escaping () -> Void) {
completionHandlers.append(completionHandler)
}
someFunctionWithEscapingClosure(_:)
函數(shù)接受一個(gè)閉包作為參數(shù)厚者,該閉包被添加到一個(gè)函數(shù)外定義的數(shù)組中躁劣。如果你不將這個(gè)參數(shù)標(biāo)記為 @escaping
,就會得到一個(gè)編譯錯(cuò)誤库菲。
自動閉包(Autoclosures)
自動閉包是一種自動創(chuàng)建的閉包账忘,用于包裝傳遞給函數(shù)作為參數(shù)的表達(dá)式。這種閉包不接受任何參數(shù)蝙昙,當(dāng)它被調(diào)用的時(shí)候闪萄,會返回被包裝在其中的表達(dá)式的值。這種便利語法讓你能夠省略閉包的花括號奇颠,用一個(gè)普通的表達(dá)式來代替顯式的閉包败去。
12.枚舉
可以定義 Swift
枚舉來存儲任意類型的關(guān)聯(lián)值,如果需要的話烈拒,每個(gè)枚舉成員的關(guān)聯(lián)值類型可以各不相同圆裕。枚舉的這種特性跟其他語言中的可識別聯(lián)合(discriminated unions
)广鳍,標(biāo)簽聯(lián)合(tagged unions
),或者變體(variants
)相似吓妆。
原始值(Raw Values)
在關(guān)聯(lián)值小節(jié)的條形碼例子中赊时,演示了如何聲明存儲不同類型關(guān)聯(lián)值的枚舉成員。作為關(guān)聯(lián)值的替代選擇行拢,枚舉成員可以被默認(rèn)值
(稱為原始值
)預(yù)填充祖秒,這些原始值的類型必須相同。
原始值的隱式賦值(Implicitly Assigned Raw Values)
enum Planet: Int {
case mercury = 1, venus, earth, mars, jupiter, saturn, uranus, neptune
}
當(dāng)使用字符串作為枚舉類型的原始值時(shí)舟奠,每個(gè)枚舉成員的隱式原始值為該枚舉成員的名稱竭缝。
enum CompassPoint: String {
case north, south, east, west
}
上面例子中,CompassPoint.south
擁有隱式原始值south
沼瘫,依次類推抬纸。
使用原始值初始化枚舉實(shí)例(Initializing from a Raw Value)
let possiblePlanet = Planet(rawValue: 7)
// possiblePlanet 類型為 Planet? 值為 Planet.uranus
13.類和結(jié)構(gòu)體
類和結(jié)構(gòu)體是人們構(gòu)建代碼所用的一種通用且靈活的構(gòu)造體。我們可以使用完全相同的語法規(guī)則來為類和結(jié)構(gòu)體定義屬性(常量耿戚、變量)和添加方法湿故,從而擴(kuò)展類和結(jié)構(gòu)體的功能。
Swift
中類和結(jié)構(gòu)體有很多共同點(diǎn)膜蛔。共同處在于:
定義屬性用于存儲值
定義方法用于提供功能
定義下標(biāo)操作使得可以通過下標(biāo)語法來訪問實(shí)例所包含的值
定義構(gòu)造器用于生成初始化值
通過擴(kuò)展以增加默認(rèn)實(shí)現(xiàn)的功能
實(shí)現(xiàn)協(xié)議以提供某種標(biāo)準(zhǔn)功能
每次定義一個(gè)新類或者結(jié)構(gòu)體的時(shí)候坛猪,實(shí)際上你是定義了一個(gè)新的Swift
類型。
struct Resolution {
var width = 0
var height = 0
}
class VideoMode {
var resolution = Resolution()
var interlaced = false
var frameRate = 0.0
var name: String?
}
let hd = Resolution(width: 1920, height: 1080)
var cinema = hd
在以上示例中飞几,聲明了一個(gè)名為hd
的常量砚哆,其值為一個(gè)初始化為全高清視頻分辨率(1920 像素寬,1080 像素高)的Resolution
實(shí)例屑墨。
然后示例中又聲明了一個(gè)名為cinema
的變量躁锁,并將hd賦值給它。因?yàn)?code>Resolution是一個(gè)結(jié)構(gòu)體,所以cinema
的值其實(shí)是hd
的一個(gè)拷貝副本,而不是hd
本身薇组。盡管hd
和cinema
有著相同的寬(width
)和高(height
)型型,但是在幕后它們是兩個(gè)完全不同的實(shí)例正什。
類是引用類型
let tenEighty = VideoMode()
tenEighty.resolution = hd
tenEighty.interlaced = true
tenEighty.name = "1080i"
tenEighty.frameRate = 25.0
let alsoTenEighty = tenEighty
alsoTenEighty.frameRate = 30.0
因?yàn)轭愂且妙愋停?code>tenEight和alsoTenEight
實(shí)際上引用的是相同的VideoMode
實(shí)例。換句話說,它們是同一個(gè)實(shí)例的兩種叫法刁标。
恒等運(yùn)算符
因?yàn)轭愂且妙愋停锌赡苡卸鄠€(gè)常量和變量在幕后同時(shí)引用同一個(gè)類實(shí)例址晕。
如果能夠判定兩個(gè)常量或者變量是否引用同一個(gè)類實(shí)例將會很有幫助膀懈。為了達(dá)到這個(gè)目的,Swift
內(nèi)建了兩個(gè)恒等運(yùn)算符:
等價(jià)于(===
)
不等價(jià)于(!==
)
指針,使用指針來引用內(nèi)存中的地址
一個(gè)引用某個(gè)引用類型實(shí)例的 Swift 常量或者變量谨垃,與 C 語言中的指針類似启搂,但是并不直接指向某個(gè)內(nèi)存地址硼控,也不要求你使用星號(*)來表明你在創(chuàng)建一個(gè)引用。Swift 中的這些引用與其它的常量或變量的定義方式相同胳赌。
在所有其它案例中牢撼,定義一個(gè)類,生成一個(gè)它的實(shí)例疑苫,并通過引用來管理和傳遞熏版。實(shí)際中,這意味著絕大部分的自定義數(shù)據(jù)構(gòu)造都應(yīng)該是類缀匕,而非結(jié)構(gòu)體纳决。
字符串(String)、數(shù)組(Array)乡小、和字典(Dictionary)類型的賦值與復(fù)制行為
Swift
中,許多基本類型饵史,諸如String
满钟,Array
和Dictionary
類型均以結(jié)構(gòu)體
的形式實(shí)現(xiàn)。這意味著被賦值給新的常量
或變量
胳喷,或者被傳入函數(shù)
或方法中時(shí)湃番,它們的值會被拷貝
。
Objective-C
中NSString
吭露,NSArray
和NSDictionary
類型均以類的形式實(shí)現(xiàn)吠撮,而并非結(jié)構(gòu)體。它們在被賦值或者被傳入函數(shù)或方法時(shí)讲竿,不會發(fā)生值拷貝泥兰,而是傳遞現(xiàn)有實(shí)例的引用。
以上是對字符串题禀、數(shù)組鞋诗、字典的“拷貝”行為的描述。在你的代碼中迈嘹,拷貝行為看起來似乎總會發(fā)生削彬。然而,Swift
在幕后只在絕對必要時(shí)才執(zhí)行實(shí)際的拷貝秀仲。Swift
管理所有的值拷貝以確保性能最優(yōu)化融痛,所以你沒必要去回避賦值來保證性能最優(yōu)化。
14.屬性
屬性將值跟特定的類
神僵、結(jié)構(gòu)
或枚舉關(guān)聯(lián)
雁刷。存儲屬性存儲常量或變量作為實(shí)例的一部分,而計(jì)算屬性計(jì)算(不是存儲)一個(gè)值挑豌。計(jì)算屬性可以用于類安券、結(jié)構(gòu)體和枚舉墩崩,存儲屬性只能用于類
和結(jié)構(gòu)體
。
存儲屬性和計(jì)算屬性通常與特定類型的實(shí)例關(guān)聯(lián)侯勉。但是鹦筹,屬性也可以直接作用于類型本身,這種屬性稱為類型屬性址貌。
存儲屬性
常量結(jié)構(gòu)體的存儲屬性
延遲存儲屬性
延遲存儲屬性是指當(dāng)?shù)谝淮伪徽{(diào)用的時(shí)候才會計(jì)算其初始值的屬性铐拐。在屬性聲明前使用 lazy
來標(biāo)示一個(gè)延遲存儲屬性。
存儲屬性和實(shí)例變量
如果您有過 Objective-C 經(jīng)驗(yàn)练对,應(yīng)該知道 Objective-C 為類實(shí)例存儲值和引用提供兩種方法遍蟋。除了屬性之外,還可以使用實(shí)例變量作為屬性值的后端存儲螟凭。
便捷 setter
聲明
全局變量和局部變量
計(jì)算屬性和屬性觀察器所描述的功能也可以用于全局變量和局部變量虚青。全局變量是在函數(shù)、方法螺男、閉包或任何類型之外定義的變量棒厘。局部變量是在函數(shù)、方法或閉包內(nèi)部定義的變量下隧。
全局的常量或變量都是延遲計(jì)算的奢人,跟延遲存儲屬性相似,不同的地方在于淆院,全局的常量或變量不需要標(biāo)記lazy
修飾符何乎。
局部范圍的常量或變量從不延遲計(jì)算。
類型屬性
類型屬性語法
15.方法(Methods)
方法是與某些特定類型相關(guān)聯(lián)的函數(shù)土辩。
類支救、結(jié)構(gòu)體、枚舉都可以定義實(shí)例方法脯燃。
實(shí)例方法為給定類型的實(shí)例封裝了具體的任務(wù)與功能搂妻。
類、結(jié)構(gòu)體辕棚、枚舉也可以定義類型方法欲主;類型方法與類型本身相關(guān)聯(lián)。類型方法與 Objective-C
中的類方法(class methods
)相似逝嚎。
修改方法的外部參數(shù)名稱(Modifying External Parameter Name Behavior for Methods)
有時(shí)為方法的第一個(gè)參數(shù)提供一個(gè)外部參數(shù)名稱是非常有用的扁瓢,盡管這不是默認(rèn)的行為。你自己可以為第一個(gè)參數(shù)添加一個(gè)顯式的外部名稱补君。
相反引几,如果你不想為方法的第二個(gè)及后續(xù)的參數(shù)提供一個(gè)外部名稱,可以通過使用下劃線(_
)作為該參數(shù)的顯式外部名稱,這樣做將覆蓋默認(rèn)行為伟桅。
self 屬性
類型的每一個(gè)實(shí)例都有一個(gè)隱含屬性叫做self敞掘,self完全等同于該實(shí)例本身。你可以在一個(gè)實(shí)例的實(shí)例方法中使用這個(gè)隱含的self屬性來引用當(dāng)前實(shí)例楣铁。
在實(shí)例方法中修改值類型
結(jié)構(gòu)體和枚舉是值類型玖雁。默認(rèn)情況下,值類型的屬性不能在它的實(shí)例方法中被修改盖腕。
類型方法 (Type Methods)
實(shí)例方法是被某個(gè)類型的實(shí)例調(diào)用的方法赫冬。你也可以定義在類型本身上調(diào)用的方法,這種方法就叫做類型方法(Type Methods)溃列。在方法的func
關(guān)鍵字之前加上關(guān)鍵字static
劲厌,來指定類型方法。類還可以用關(guān)鍵字class
來允許子類重寫父類的方法實(shí)現(xiàn)听隐。
在 Objective-C
中补鼻,你只能為 Objective-C
的類類型(classes
)定義類型方法(type-level methods
)。在 Swift
中雅任,你可以為所有的類辽幌、結(jié)構(gòu)體和枚舉定義類型方法。每一個(gè)類型方法都被它所支持的類型顯式包含
椿访。
class SomeClass {
class func someTypeMethod() {
// type method implementation goes here
}
}
SomeClass.someTypeMethod()
在類型方法的方法體(body)中,self
指向這個(gè)類型本身虑润,而不是類型的某個(gè)實(shí)例成玫。這意味著你可以用self
來消除類型屬性和類型方法參數(shù)之間的歧義(類似于我們在前面處理實(shí)例屬性和實(shí)例方法參數(shù)時(shí)做的那樣)。