文章來(lái)自菜鳥(niǎo)教程。
Swift
數(shù)據(jù)類(lèi)型
Int
??一般來(lái)說(shuō)票彪,你不需要專(zhuān)門(mén)指定整數(shù)的長(zhǎng)度Swift提供了一個(gè)特殊的整數(shù)類(lèi)型Int
,長(zhǎng)度與當(dāng)前平臺(tái)的原生字長(zhǎng)相同。
- 在32位平臺(tái)上捆等,
Int
和Int32
長(zhǎng)度相同。 - 在64位平臺(tái)上续室,
Int
和Int64
長(zhǎng)度相同栋烤。
??除非你需要特定長(zhǎng)度的整數(shù),一般來(lái)說(shuō)使用Int
就夠了挺狰。這可以提高代碼一致性和可復(fù)用性明郭。即使是在32位平臺(tái)上,Int可以存儲(chǔ)的整數(shù)范圍也可以達(dá)到-2,147,483,648 ~ 2,147,483,647她渴,大多數(shù)時(shí)候這已經(jīng)足夠大了达址。
UInt
??Swift也提供了一個(gè)特殊的無(wú)符號(hào)類(lèi)型UInt
,長(zhǎng)度與當(dāng)前平臺(tái)的原生字長(zhǎng)相同趁耗。
- 在32位平臺(tái)上沉唠,UInt和UInt32長(zhǎng)度相同。
- 在64位平臺(tái)上苛败,UInt和UInt64長(zhǎng)度相同满葛。
注意: 盡量不要使用UInt径簿,除非你真的需要存儲(chǔ)一個(gè)和當(dāng)前平臺(tái)原生字長(zhǎng)相同的無(wú)符號(hào)整數(shù)。除了這種情況嘀韧,最好使用Int篇亭,即使你要存儲(chǔ)的值已知是非負(fù)的。統(tǒng)一使用Int可以提高代碼的可復(fù)用性锄贷,避免不同類(lèi)型數(shù)字之間的轉(zhuǎn)換译蒂,并且匹配數(shù)字的類(lèi)型推斷。
浮點(diǎn)數(shù):Float谊却、Double
- Float 表示32位浮點(diǎn)數(shù)
- Double 表示64位浮點(diǎn)數(shù)
布爾值 Bool
??布爾值指邏輯上的值柔昼,它們只能是真或者假。true 和 false炎辨。
字符串 String
"Hello, World!"
字符 Character
"C"
可選類(lèi)型 Optional
??使用可選類(lèi)型來(lái)處理值可能缺失的情況捕透。可選類(lèi)型表示有值或沒(méi)有值碴萧。
可以按照下面兩種方式聲明變量:
var optionalInteger: Int?
var optionalInteger: Optional<Int>
// 注意乙嘀,在類(lèi)型和?之間沒(méi)有空格。
??Optional 是一個(gè)含有兩種情況的枚舉破喻,None 和 Some(T)虎谢,用來(lái)表示可能有或可能沒(méi)有值。任何類(lèi)型都可以明確聲明為(或者隱式轉(zhuǎn)換)可選類(lèi)型曹质。當(dāng)聲明一個(gè)可選類(lèi)型的時(shí)候嘉冒,要確保用括號(hào)給 ? 操作符一個(gè)合適的范圍。例如咆繁,聲明可選整數(shù)數(shù)組讳推,應(yīng)該寫(xiě)成 (Int[])? 寫(xiě)成 Int[]? 會(huì)報(bào)錯(cuò)。
??當(dāng)你聲明一個(gè)可選變量或者可選屬性的時(shí)候沒(méi)有提供初始值玩般,它的值會(huì)默認(rèn)為 nil银觅。
??如果一個(gè)可選類(lèi)型的實(shí)例包含一個(gè)值,你可以用后綴操作符 坏为!來(lái)訪問(wèn)這個(gè)值究驴。
optionalInteger = 42
optionalInteger! // 42
??使用操作符!去獲取值為nil的可選變量會(huì)有運(yùn)行時(shí)錯(cuò)誤。
let myString:String? = nil
if myString != nil {
print(myString)
} else {
print("字符串myString為 nil")
}
強(qiáng)制解析
??當(dāng)你確定可選類(lèi)型確實(shí)包含值之后,你可以在可選的名字后面加一個(gè)感嘆號(hào)(!)來(lái)獲取值荧关。這個(gè)感嘆號(hào)表示"我知道這個(gè)可選有值,請(qǐng)使用它熙侍。"這被稱(chēng)為可選值的強(qiáng)制解析(forced unwrapping)。
var myString:String?
myString = "Hello, Swift!"
if myString != nil {
print(myString)
print(myString!)//強(qiáng)制解析
} else {
print("myString 值為 nil")
}
使用!來(lái)獲取一個(gè)不存在的可選值會(huì)導(dǎo)致運(yùn)行時(shí)錯(cuò)誤。使用!來(lái)強(qiáng)制解析值之前蛉抓,一定要確定可選包含一個(gè)非nil的值庆尘。
自動(dòng)解析
??你可以在聲明可選變量時(shí)使用感嘆號(hào)(!)替換問(wèn)號(hào)(?)。這樣可選變量在使用時(shí)就不需要再加一個(gè)感嘆號(hào)(!)來(lái)獲取值巷送,它會(huì)自動(dòng)解析驶忌。
var myString:String!
myString = "Hello, Swift!"
if myString != nil {
print(myString)
} else {
print("myString 值為 nil")
}
可選綁定
??使用可選綁定(optional binding)來(lái)判斷可選類(lèi)型是否包含值,如果包含就把值賦給一個(gè)臨時(shí)常量或者變量笑跛「赌В可選綁定可以用在if和while語(yǔ)句中來(lái)對(duì)可選類(lèi)型的值進(jìn)行判斷并把值賦給一個(gè)常量或者變量。
var myString:String?
myString = "Hello, Swift!"
if let yourString = myString {
print("你的字符串值為 - \(yourString)")
} else {
print("你的字符串沒(méi)有值")
}
數(shù)值范圍
設(shè)備 | 關(guān)鍵字 | 區(qū)間值 |
---|---|---|
Int8 | 1字節(jié) | -128 ~ 127 |
UInt8 | 1字節(jié) | 0~ 255 |
Int32 | 4字節(jié) | -2147483648 ~ 2147483647 |
UInt32 | 4字節(jié) | 0~ 4294967295 |
Int64 | 8字節(jié) | -9223372036854775808 ~ 9223372036854775807 |
UInt64 | 8字節(jié) | 0 ~ 18446744073709551615 |
Float | 4字節(jié) | 1.2E-38 ~ 3.4E+38 |
Double | 8字節(jié) | 2.3E-308 ~ 1.7E+308 |
類(lèi)型別名
??使用typealias關(guān)鍵字 比如:定義Int
別名為pinguiInt
飞蹂。
typealias pinguInt = Int
類(lèi)型推斷 類(lèi)型安全
??Swift是一個(gè)類(lèi)型安全(type safe)的語(yǔ)言抒抬。
??由于Swift是類(lèi)型安全的,所以它會(huì)在編譯你的代碼時(shí)進(jìn)行類(lèi)型檢查(type checks)晤柄,并把不匹配的類(lèi)型標(biāo)記為錯(cuò)誤。這可以讓你在開(kāi)發(fā)的時(shí)候盡早發(fā)現(xiàn)并修復(fù)錯(cuò)誤妖胀。
??比如像下面這樣寫(xiě)會(huì)報(bào)錯(cuò):
var a = 42
a = "This is hello"
print(a)
cannot assign value of type 'String' to type 'Int', a默認(rèn)為Int類(lèi)型
類(lèi)型標(biāo)注
??當(dāng)你聲明常量或者變量的時(shí)候可以加上類(lèi)型標(biāo)注(type annotation)芥颈,說(shuō)明常量或者變量中要存儲(chǔ)的值的類(lèi)型。如果要添加類(lèi)型標(biāo)注赚抡,需要在常量或者變量名后面加上一個(gè)冒號(hào)和空格爬坑,然后加上類(lèi)型名稱(chēng)。
let constB:Float = 3.14159
運(yùn)算符
算術(shù)運(yùn)算符
- 涂臣、- 盾计、* 、/ 赁遗、%
注意:swift3 中已經(jīng)取消了++署辉、--。
var A = 10
var B = 20
print("A + B 結(jié)果為:\(A + B)")
print("A - B 結(jié)果為:\(A - B)")
print("A * B 結(jié)果為:\(A * B)")
print("B / A 結(jié)果為:\(B / A)")
A += 1 // 類(lèi)似 A++
print("A += 1 后 A 的值為 \(A)")
B -= 1 // 類(lèi)似 B--
print("B -= 1 后 B 的值為 \(B)")
比較運(yùn)算符
== 岩四、!= 哭尝、> 、< 剖煌、>= 材鹦、<=
邏輯運(yùn)算符
&& 、|| 耕姊、~
位運(yùn)算符
~ 桶唐、& 、| 茉兰、^尤泽,分別為取反,按位與,按位或安吁,按位異或醉蚁。
賦值運(yùn)算符
= 、+= 鬼店、-= 网棍、/= 、%= 妇智、<<= 滥玷、>>= 、&= 巍棱、^= 惑畴、|=
區(qū)間運(yùn)算符(閉區(qū)間運(yùn)算符1...5/半開(kāi)區(qū)間運(yùn)算符1..<5)
//閉區(qū)間運(yùn)算符
for index in 1...3 {
print("\(index) * 3 = \(index * 3)")
}
//半開(kāi)區(qū)間運(yùn)算符
for index in 1..<3 {
print("\(index) * 3 = \(index * 3)")
}
其它運(yùn)算符
- 一元運(yùn)算符 如: -a
- 二元運(yùn)算符 如: 2 + 3
- 三元運(yùn)算符 如: a ? b : c
條件語(yǔ)句
if if...else... switch語(yǔ)句
循環(huán)語(yǔ)句
for-in for while repeat...while(類(lèi)似 while 語(yǔ)句,區(qū)別在于判斷循環(huán)條件之前,先執(zhí)行一次循環(huán)的代碼塊航徙。)
循環(huán)控制語(yǔ)句
continue break fallthrough(如果在一個(gè)case執(zhí)行完后如贷,繼續(xù)執(zhí)行下面的case,需要使用fallthrough(貫穿)關(guān)鍵字到踏。)
字符串
創(chuàng)建字符串
// 使用字符串字面量
var strA = "Hello, World!"
print( strA )
// String 實(shí)例化
var strB = String("Hello, World!")
print( strB )
空字符串
??你可以使用空的字符串字面量賦值給變量或初始化一個(gè)String類(lèi)的實(shí)例來(lái)初始值一個(gè)空的字符串杠袱。 我們可以使用字符串屬性isEmpty
來(lái)判斷字符串是否為空。
// 使用字符串字面量創(chuàng)建空字符串
var strA = ""
if strA.isEmpty {
print( "strA 是空的" )
} else {
print( "strA 不是空的" )
}
// 實(shí)例化 String 類(lèi)來(lái)創(chuàng)建空字符串
let strB = String()
if strB.isEmpty {
print( "strB 是空的" )
} else {
print( "strB 不是空的" )
}
字符串插值
字符串插值是一種構(gòu)建新字符串的方式窝稿,可以在其中包含常量楣富、變量、字面量和表達(dá)式伴榔。 您插入的字符串字面量的每一項(xiàng)都在以反斜線為前綴的圓括號(hào)中纹蝴。
//字符串插值
var varA = 20
let constA = 100
var varC:Float = 20.0
var stringA2 = "\(varA) 乘于 \(constA) 等于 \(varC * 100)"
print( stringA2 )
字符串連接
-
可以通過(guò) "+" 連接。
let strA = "百度:" let strB = "http://www.baidu.com" var strC = strA + strB print( strC )
-
使用
append
方法var strA:String = "Hello " let strB:Character = "G" strA.append(strB) print("strA=\(strA)")
字符串長(zhǎng)度
var str = "www.baidu.com"
print("\(str)的長(zhǎng)度為\(str.count)")
字符串比較
你可以使用 == 來(lái)比較兩個(gè)字符串是否相等.
var varA2 = "Hello, Swift!"
var varB2 = "Hello, World!"
if varA2 == varB2 {
print( "\(varA2) 與 \(varB2) 是相等的" )
} else {
print( "\(varA2) 與 \(varB2) 是不相等的" )
}
Unicode 字符串
Unicode 是一個(gè)國(guó)際標(biāo)準(zhǔn)踪少,用于文本的編碼塘安,Swift 的 String 類(lèi)型是基于 Unicode建立的。你可以循環(huán)迭代出字符串中 UTF-8 與 UTF-16 的編碼援奢。
var unicodeString = "swift"
print("UTF-8 編碼: ")
for code in unicodeString.utf8 {
print("\(code) ")
}
字符
Swift 的字符是一個(gè)單一的字符字符串字面量耙旦,數(shù)據(jù)類(lèi)型為 Character。
let char1: Character = "A"
let char2: Character = "B"
print("char1 的值為 \(char1)")
print("char2 的值為 \(char2)")
如果你想在 Character(字符) 類(lèi)型的常量中存儲(chǔ)更多的字符萝究,則程序執(zhí)行會(huì)報(bào)錯(cuò) 比如:
let char: Character = "AB"
空字符變量
Swift 中不能創(chuàng)建空的 Character(字符) 類(lèi)型變量或常量, 會(huì)報(bào)錯(cuò)免都。
let char1: Character = ""
var char2: Character = ""
print("char1 的值為 \(char1)")
print("char2 的值為 \(char2)")
遍歷字符串中的字符
Swift的String類(lèi)型表示特定序列的 Character(字符) 類(lèi)型值的集合。 每一個(gè)字符值代表一個(gè) Unicode 字符帆竹。
您可通過(guò)for-in循環(huán)來(lái)遍歷字符串中的characters屬性來(lái)獲取每一個(gè)字符的值绕娘。
for ch in "baidu.com".characters {
print(ch)
}
Swift 數(shù)組
Swift 數(shù)組使用有序列表存儲(chǔ)同一類(lèi)型的多個(gè)值。相同的值可以多次出現(xiàn)在一個(gè)數(shù)組的不同位置中栽连。
Swift 數(shù)組會(huì)強(qiáng)制檢測(cè)元素的類(lèi)型险领,如果類(lèi)型不同則會(huì)報(bào)錯(cuò)侨舆,Swift 數(shù)組應(yīng)該遵循像Array<Element>這樣的形式,其中Element是這個(gè)數(shù)組中唯一允許存在的數(shù)據(jù)類(lèi)型绢陌。
如果創(chuàng)建一個(gè)數(shù)組挨下,并賦值給一個(gè)變量,則創(chuàng)建的集合就是可以修改的脐湾。這意味著在創(chuàng)建數(shù)組后臭笆,可以通過(guò)添加、刪除秤掌、修改的方式改變數(shù)組里的項(xiàng)目愁铺。如果將一個(gè)數(shù)組賦值給常量,數(shù)組就不可更改闻鉴,并且數(shù)組的大小和內(nèi)容都不可以修改茵乱。
創(chuàng)建數(shù)組
使用構(gòu)造語(yǔ)法來(lái)創(chuàng)建一個(gè)由特定數(shù)據(jù)類(lèi)型構(gòu)成的空數(shù)組。
var array = [Int]()
創(chuàng)建了一個(gè)類(lèi)型為 Int 孟岛,數(shù)量為 3瓶竭,初始值為 2 的數(shù)組。
var array = [Int](repeating: 2, count: 3)
創(chuàng)建了含有三個(gè)元素的數(shù)組渠羞。
var array:[Int] = [10, 20, 30]
訪問(wèn)數(shù)組
根據(jù)數(shù)組的索引來(lái)訪問(wèn)數(shù)組的元素斤贰。
var arrayValue = array[index]
index 索引從 0 開(kāi)始,即索引 0 對(duì)應(yīng)第一個(gè)元素堵未,索引 1 對(duì)應(yīng)第二個(gè)元素,以此類(lèi)推盏触。
var someInts = [Int](repeating: 10, count: 3)
var someVar = someInts[0]
print( "第一個(gè)元素的值 \(someVar)" )
print( "第二個(gè)元素的值 \(someInts[1])" )
print( "第三個(gè)元素的值 \(someInts[2])" )
修改數(shù)組
你可以使用 append() 方法或者賦值運(yùn)算符 += 在數(shù)組末尾添加元素渗蟹,如下所示,我們初始化一個(gè)數(shù)組赞辩,并向其添加元素雌芽。
var someInts = [Int]()
someInts.append(20)
someInts.append(30)
someInts += [40]
var someVar = someInts[0]
print( "第一個(gè)元素的值 \(someVar)" ) // 20
print( "第二個(gè)元素的值 \(someInts[1])" ) // 30
print( "第三個(gè)元素的值 \(someInts[2])" ) // 40
也可以通過(guò)索引修改數(shù)組元素的值。
someInts[2] = 50
print( "第一個(gè)元素的值 \(someVar)" ) // 20
print( "第二個(gè)元素的值 \(someInts[1])" ) // 30
print( "第三個(gè)元素的值 \(someInts[2])" ) // 50
遍歷數(shù)組
可以使用for-in循環(huán)來(lái)遍歷所有數(shù)組中的數(shù)據(jù)項(xiàng)辨嗽。
var someStrs = [String]()
someStrs.append("Apple")
someStrs.append("Amazon")
someStrs.append("Tencent")
someStrs += ["Google"]
for item in someStrs {
print(item)
}
如果同時(shí)需要每個(gè)數(shù)據(jù)項(xiàng)的值和索引值世落,可以使用 String 的 enumerate() 方法來(lái)進(jìn)行數(shù)組遍歷。
var array = [String]()
array.append("Apple")
array.append("Amazon")
array.append("Tencent")
array += ["Google"]
for (index, item) in array.enumerated() {
print("在index=\(index)的值為\(item)")
}
合并數(shù)組
可以使用加法操作符(+)來(lái)合并兩種已存在的相同類(lèi)型數(shù)組糟需。新數(shù)組的數(shù)據(jù)類(lèi)型會(huì)從兩個(gè)數(shù)組的數(shù)據(jù)類(lèi)型中推斷出來(lái)屉佳。
var intsA = [Int](repeating: 2, count:2)
var intsB = [Int](repeating: 1, count:3)
var intsC = intsA + intsB
for item in intsC {
print(item)
}
count 屬性
使用 count 屬性來(lái)計(jì)算數(shù)組元素個(gè)數(shù)。
var intsA = [Int](count:2, repeatedValue: 2)
var intsB = [Int](count:3, repeatedValue: 1)
var intsC = intsA + intsB
print("intsA 元素個(gè)數(shù)為 \(intsA.count)")
print("intsB 元素個(gè)數(shù)為 \(intsB.count)")
print("intsC 元素個(gè)數(shù)為 \(intsC.count)")
isEmpty 屬性
可以通過(guò)只讀屬性 isEmpty 來(lái)判斷數(shù)組是否為空洲押,返回布爾值武花。
var intsA = [Int](count:2, repeatedValue: 2)
var intsB = [Int](count:3, repeatedValue: 1)
var intsC = [Int]()
print("intsA.isEmpty = \(intsA.isEmpty)")
print("intsB.isEmpty = \(intsB.isEmpty)")
print("intsC.isEmpty = \(intsC.isEmpty)")
Swift 字典
Swift 字典用來(lái)存儲(chǔ)無(wú)序的相同類(lèi)型數(shù)據(jù)的集合,Swift 字典會(huì)強(qiáng)制檢測(cè)元素的類(lèi)型杈帐,如果類(lèi)型不同則會(huì)報(bào)錯(cuò)体箕。
Swift 字典每個(gè)值(value)都關(guān)聯(lián)唯一的鍵(key)专钉,鍵作為字典中的這個(gè)值數(shù)據(jù)的標(biāo)識(shí)符。
和數(shù)組中的數(shù)據(jù)項(xiàng)不同累铅,字典中的數(shù)據(jù)項(xiàng)并沒(méi)有具體順序跃须。我們?cè)谛枰ㄟ^(guò)標(biāo)識(shí)符(鍵)訪問(wèn)數(shù)據(jù)的時(shí)候使用字典,這種方法很大程度上和我們?cè)诂F(xiàn)實(shí)世界中使用字典查字義的方法一樣娃兽。
Swift 字典的key沒(méi)有類(lèi)型限制可以是整型或字符串菇民,但必須是唯一的。
如果創(chuàng)建一個(gè)字典换薄,并賦值給一個(gè)變量玉雾,則創(chuàng)建的字典就是可以修改的。這意味著在創(chuàng)建字典后轻要,可以通過(guò)添加复旬、刪除、修改的方式改變字典里的項(xiàng)目冲泥。如果將一個(gè)字典賦值給常量驹碍,字典就不可修改,并且字典的大小和內(nèi)容都不可以修改凡恍。
創(chuàng)建字典
創(chuàng)建一個(gè)特定類(lèi)型的空字典志秃。
var dic = [keyType : ValueType]()
創(chuàng)建一個(gè)字典的實(shí)例。
var dic : [Int:String] = [1:"One", 2:"Two"]
訪問(wèn)字典
根據(jù)字典的key來(lái)訪問(wèn)字典嚼酝。
var value = dic[key]
修改字典
我可以使用 updateValue(forKey:) 增加或更新字典的內(nèi)容浮还。如果 key 不存在,則添加值闽巩,如果存在則修改 key 對(duì)應(yīng)的值钧舌。updateValue(_:forKey:)方法返回Optional值。
var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
var oldVal = someDict.updateValue("One 新的值", forKey: 1)
var someVar = someDict[1]
print("key = 1 舊的值 \(oldVal)")
print("key = 1 的值為 \(someVar)")
print("key = 2 的值為 \(someDict[2])")
print("key = 3 的值為 \(someDict[3])")
也可以通過(guò)指定的key來(lái)修改字典的值涎跨。
someDict[1] = "sfef"
移除Key-Value
可以使用 removeValueForKey() 方法來(lái)移除字典 key-value 對(duì)洼冻。如果 key 存在該方法返回移除的值,如果不存在返回 nil 隅很。
var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
var removedValue = someDict.removeValue(forKey: 2)
print("key = 1 的值為 \(someDict[1])")
print("removedValue 的值為 \(removedValue)")
print("key = 2 的值為 \(someDict[2])")
print("key = 3 的值為 \(someDict[3])")
遍歷字典
可以使用 for-in 循環(huán)來(lái)遍歷某個(gè)字典中的鍵值對(duì)撞牢。
var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
for (key, vale) in someDict {
print("key = \(key) value = \(vale)")
}
字典轉(zhuǎn)換為數(shù)組
可以提取字典的鍵值(key-value)對(duì),并轉(zhuǎn)換為獨(dú)立的數(shù)組叔营。
var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
let dictKeys = [Int](someDict.keys)
let dictValues = [String](someDict.values)
print("輸出字典的鍵(key)")
for (key) in dictKeys {
print("\(key)")
}
print("輸出字典的值(value)")
for (value) in dictValues {
print("\(value)")
}
count 屬性
我們可以使用只讀的 count 屬性來(lái)計(jì)算字典有多少個(gè)鍵值對(duì)屋彪。
var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
print("someDict 含有 \(someDict.count) 個(gè)鍵值對(duì)")
isEmpty 屬性
可以通過(guò)只讀屬性 isEmpty 來(lái)判斷字典是否為空,返回布爾值绒尊。
var someDict1:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
var someDict2:[Int:String] = [Int:String]()
print("someDict1 = \(someDict1.isEmpty)")
print("someDict2 = \(someDict2.isEmpty)")
Swift 函數(shù)
Swift 函數(shù)用來(lái)完成特定任務(wù)的獨(dú)立的代碼塊撼班。
Swift使用一個(gè)統(tǒng)一的語(yǔ)法來(lái)表示簡(jiǎn)單的C語(yǔ)言風(fēng)格的函數(shù)到復(fù)雜的Objective-C語(yǔ)言風(fēng)格的方法。
- 函數(shù)聲明: 告訴編譯器函數(shù)的名字垒酬,返回類(lèi)型及參數(shù)砰嘁。
- 函數(shù)定義: 提供了函數(shù)的實(shí)體件炉。
Swift 函數(shù)包含了參數(shù)類(lèi)型及返回值類(lèi)型。
函數(shù)定義
Swift 定義函數(shù)使用關(guān)鍵字 func矮湘。
定義函數(shù)的時(shí)候斟冕,可以指定一個(gè)或多個(gè)輸入?yún)?shù)和一個(gè)返回值類(lèi)型。
每個(gè)函數(shù)都有一個(gè)函數(shù)名來(lái)描述它的功能缅阳。通過(guò)函數(shù)名以及對(duì)應(yīng)類(lèi)型的參數(shù)值來(lái)調(diào)用這個(gè)函數(shù)磕蛇。函數(shù)的參數(shù)傳遞的順序必須與參數(shù)列表相同。
函數(shù)的實(shí)參傳遞的順序必須與形參列表相同十办,-> 后定義函數(shù)的返回值類(lèi)型秀撇。
語(yǔ)法
func funcName(形參) -> returnType {
statement1
statement2
...
return parameters
}
我們定義了一個(gè)函數(shù)名為 runoob 的函數(shù),形參的數(shù)據(jù)類(lèi)型為 String向族,返回值也為 String呵燕。
func runoob(site:String) -> String {
return site
}
函數(shù)調(diào)用
可以通過(guò)函數(shù)名以及對(duì)應(yīng)類(lèi)型的參數(shù)值來(lái)調(diào)用函數(shù),函數(shù)的參數(shù)傳遞的順序必須與參數(shù)列表相同件相。
函數(shù)可以接受一個(gè)或者多個(gè)參數(shù)再扭,這些參數(shù)被包含在函數(shù)的括號(hào)之中,以逗號(hào)分隔夜矗。
func runoob(name: String, site: String) -> String {
return name + site
}
也可以創(chuàng)建不帶參數(shù)的函數(shù)泛范。
func funcname() -> datatype {
return datatype
}
元祖作為函數(shù)返回值
函數(shù)返回值類(lèi)型可以是字符串,整型紊撕,浮點(diǎn)型等罢荡。
元組與數(shù)組類(lèi)似,不同的是对扶,元組中的元素可以是任意類(lèi)型区赵,使用的是圓括號(hào)。
你可以用元組(tuple)類(lèi)型讓多個(gè)值作為一個(gè)復(fù)合值從函數(shù)中返回辩稽。
下面定義了一個(gè)名為minMax(_:)的函數(shù)惧笛,作用是在一個(gè)Int數(shù)組中找出最小值與最大值从媚。
func minMax(array: [Int]) -> (min: Int, max: Int) {
var currentMin = array[0]
var currentMax = array[0]
for value in array[1..<array.count] {
if value < currentMin {
currentMin = value
} else if value > currentMax {
currentMax = value
}
}
return (currentMin, currentMax)
}
minMax(_:)函數(shù)返回一個(gè)包含兩個(gè)Int值的元組逞泄,這些值被標(biāo)記為min和max,以便查詢函數(shù)的返回值時(shí)可以通過(guò)名字訪問(wèn)它們拜效。
如果你不確定返回的元組一定不為nil喷众,那么你可以返回一個(gè)可選的元組類(lèi)型。
你可以通過(guò)在元組類(lèi)型的右括號(hào)后放置一個(gè)問(wèn)號(hào)來(lái)定義一個(gè)可選元組紧憾,例如(Int, Int)?或(String, Int, Bool)?
注意:
可選元組類(lèi)型如(Int, Int)?與元組包含可選類(lèi)型如(Int?, Int?)是不同的.可選的元組類(lèi)型到千,整個(gè)元組是可選的,而不只是元組中的每個(gè)元素值赴穗。
前面的minMax(:)函數(shù)返回了一個(gè)包含兩個(gè)Int值的元組憔四。但是函數(shù)不會(huì)對(duì)傳入的數(shù)組執(zhí)行任何安全檢查膀息,如果array參數(shù)是一個(gè)空數(shù)組,如上定義的minMax(:)在試圖訪問(wèn)array[0]時(shí)會(huì)觸發(fā)一個(gè)運(yùn)行時(shí)錯(cuò)誤了赵。
為了安全地處理這個(gè)"空數(shù)組"問(wèn)題潜支,將minMax(_:)函數(shù)改寫(xiě)為使用可選元組返回類(lèi)型,并且當(dāng)數(shù)組為空時(shí)返回nil柿汛。
func minMax(array: [Int]) -> (min: Int, max: Int)? {
if array.isEmpty { return nil }
var currentMin = array[0]
var currentMax = array[0]
for value in array[1..<array.count] {//從第二個(gè)元素開(kāi)始遍歷
if value < currentMin {
currentMin = value
} else if value > currentMax {
currentMax = value
}
}
return (currentMin, currentMax)
}
沒(méi)有返回值函數(shù)
func funcname(site:String) {
...
}
函數(shù)參數(shù)名稱(chēng)
函數(shù)參數(shù)都有一個(gè)外部參數(shù)名和一個(gè)局部參數(shù)名冗酿。
局部參數(shù)名在函數(shù)的實(shí)現(xiàn)內(nèi)部使用。
可以在局部參數(shù)名前指定外部參數(shù)名络断,中間以空格分隔裁替,外部參數(shù)名用于在函數(shù)調(diào)用時(shí)傳遞給函數(shù)的參數(shù)。
func pow(firstArg a: Int, secondArg b: Int) -> Int {
var res = a
for _ in 1..<b {
res = res * a
}
print(res)
return res
}
pow(firstArg:5, secondArg:3)
注意:如果你提供了外部參數(shù)名貌笨,那么函數(shù)在被調(diào)用時(shí)弱判,必須使用外部參數(shù)名。
可變參數(shù)
可變參數(shù)可以接受零個(gè)或多個(gè)值躁绸。函數(shù)調(diào)用時(shí)裕循,你可以用可變參數(shù)來(lái)指定函數(shù)參數(shù),其數(shù)量是不確定的净刮。
可變參數(shù)通過(guò)在變量類(lèi)型名后面加入(...)的方式來(lái)定義剥哑。
func vari<N>(members: N...){
for i in members {
print(i)
}
}
vari(members: 4,3,5)
常量、變量及I/O參數(shù)
一般默認(rèn)在函數(shù)中定義的參數(shù)都是常量參數(shù)淹父,也就是這個(gè)參數(shù)你只可以查詢使用株婴,不能改變它的值。
如果想要聲明一個(gè)變量參數(shù)暑认,可以在參數(shù)定義前加 inout 關(guān)鍵字困介,這樣就可以改變這個(gè)參數(shù)的值了。
func swapTwoInts(_ a: inout Int, _ b: inout Int) {
let temporaryA = a
a = b
b = temporaryA
}
var x = 1
var y = 5
swapTwoInts(&x, &y)
print("x 現(xiàn)在的值 \(x), y 現(xiàn)在的值 \(y)")
注意:注意的是蘸际,在傳入 swapTwoInts(::) 函數(shù)前座哩,都加了 & 的前綴。
函數(shù)的類(lèi)型及使用
每個(gè)函數(shù)都有種特定的函數(shù)類(lèi)型粮彤,由函數(shù)的參數(shù)類(lèi)型和返回類(lèi)型組成根穷。
使用函數(shù)類(lèi)型
在 Swift 中,使用函數(shù)類(lèi)型就像使用其他類(lèi)型一樣导坟。例如屿良,你可以定義一個(gè)類(lèi)型為函數(shù)的常量或變量,并將適當(dāng)?shù)暮瘮?shù)賦值給它惫周。
var addition: (Int, Int) -> Int = sum
"定義一個(gè)叫做 addition 的變量尘惧,參數(shù)與返回值類(lèi)型均是 Int ,并讓這個(gè)新變量指向 sum 函數(shù)"递递。
sum 和 addition 有同樣的類(lèi)型喷橙,所以以上操作是合法的啥么。
現(xiàn)在,你可以用 addition 來(lái)調(diào)用被賦值的函數(shù)了贰逾。
func sum(a: Int, b: Int) -> Int {
return a + b
}
var addition: (Int, Int) -> Int = sum
print("輸出結(jié)果: \(addition(40, 89))")//129
函數(shù)類(lèi)型作為參數(shù)類(lèi)型饥臂、函數(shù)類(lèi)型作為返回類(lèi)型
可以將函數(shù)作為參數(shù)傳遞給另外一個(gè)參數(shù)。
func sum(a: Int, b: Int) -> Int {
return a + b
}
var addition: (Int, Int) -> Int = sum
print("輸出結(jié)果: \(addition(40, 89))")
func another(addition: (Int, Int) -> Int, a: Int, b: Int) {
print("輸出結(jié)果: \(addition(a, b))")
}
another(addition: sum, a: 10, b: 20)
函數(shù)嵌套
函數(shù)嵌套指的是函數(shù)內(nèi)定義一個(gè)新的函數(shù)似踱,外部的函數(shù)可以調(diào)用函數(shù)內(nèi)定義的函數(shù)隅熙。
func calcDecrement(forDecrement total: Int) -> () -> Int {
var overallDecrement = 0
func decrementer() -> Int {
overallDecrement -= total
return overallDecrement
}
return decrementer
}
let decrem = calcDecrement(forDecrement: 30)
print(decrem()) //-30
說(shuō)明:一個(gè)calcDecrement函數(shù),它有一個(gè)Int型的參數(shù)total核芽,并且他還有一個(gè)外不去參數(shù)名字forDecrement囚戚,在調(diào)用的時(shí)候必須使用這個(gè)外部名字,返回一個(gè)()->Int函數(shù)轧简。
Swift 閉包
閉包(Closures)是自包含的功能代碼塊驰坊,可以在代碼中使用或者用來(lái)作為參數(shù)傳值。
Swift 中的閉包與 C 和 Objective-C 中的代碼塊(blocks)以及其他一些編程語(yǔ)言中的 匿名函數(shù)比較相似哮独。
全局函數(shù)和嵌套函數(shù)其實(shí)就是特殊的閉包拳芙。
閉包的形式:
全局函數(shù) | 嵌套函數(shù) | 閉包表達(dá)式 |
---|---|---|
有名字但不能捕獲任何值 | 有名字,也能捕獲封閉函數(shù)內(nèi)的值 | 無(wú)名閉包皮璧,使用輕量級(jí)語(yǔ)法舟扎,可以根據(jù)上下文環(huán)境捕獲值 |
Swift中的閉包有很多優(yōu)化的地方:
- 根據(jù)上下文推斷參數(shù)和返回值類(lèi)型
- 從單行表達(dá)式閉包中隱式返回(也就是閉包體只有一行代碼,可以省略return)
- 可以使用簡(jiǎn)化參數(shù)名悴务,如1(從0開(kāi)始睹限,表示第i個(gè)參數(shù)...)
- 提供了尾隨閉包語(yǔ)法(Trailing closure syntax)
語(yǔ)法:
以下定義了一個(gè)接收參數(shù)并返回指定類(lèi)型的閉包語(yǔ)法:
{(parameters) -> return type in
statements
}
以下閉包形式接收兩個(gè)參數(shù)并返回布爾值:
{(Int, Int) -> Bool in
Statement1
Statement 2
---
Statement n
}
let divide = {(val1: Int, val2: Int) -> Int in
return val1 / val2
}
let result = divide(200, 20)
print (result) //10
閉包表達(dá)式
閉包表達(dá)式是一種利用簡(jiǎn)潔語(yǔ)法構(gòu)建內(nèi)聯(lián)閉包的方式。 閉包表達(dá)式提供了一些語(yǔ)法優(yōu)化讯檐,使得撰寫(xiě)閉包變得簡(jiǎn)單明了羡疗。
sorted 方法
Swift 標(biāo)準(zhǔn)庫(kù)提供了名為 sorted(by:) 的方法,會(huì)根據(jù)您提供的用于排序的閉包函數(shù)將已知類(lèi)型數(shù)組中的值進(jìn)行排序别洪。
排序完成后叨恨,sorted(by:) 方法會(huì)返回一個(gè)與原數(shù)組大小相同,包含同類(lèi)型元素且元素已正確排序的新數(shù)組挖垛。原數(shù)組不會(huì)被 sorted(by:) 方法修改痒钝。
sorted(by:)方法需要傳入兩個(gè)參數(shù):
- 已知類(lèi)型的數(shù)組
- 閉包函數(shù),該閉包函數(shù)需要傳入與數(shù)組元素類(lèi)型相同的兩個(gè)值晕换,并返回一個(gè)布爾類(lèi)型值來(lái)表明當(dāng)排序結(jié)束后傳入的第一個(gè)參數(shù)排在第二個(gè)參數(shù)前面還是后面午乓。如果第一個(gè)參數(shù)值出現(xiàn)在第二個(gè)參數(shù)值前面站宗,排序閉包函數(shù)需要返回 true闸准,反之返回 false。
let names = ["AT", "AE", "D", "S", "BE"]
// 使用普通函數(shù)(或內(nèi)嵌函數(shù))提供排序功能,閉包函數(shù)類(lèi)型需為(String, String) -> Bool梢灭。
func backwards(s1: String, s2: String) -> Bool {
return s1 > s2
}
var reversed = names.sorted(by: backwards)
print(reversed) //["S", "D", "BE", "AT", "AE"]
參數(shù)名稱(chēng)縮寫(xiě)
Swift 自動(dòng)為內(nèi)聯(lián)函數(shù)提供了參數(shù)名稱(chēng)縮寫(xiě)功能夷家,您可以直接通過(guò)1,$2來(lái)順序調(diào)用閉包的參數(shù)蒸其。
let names = ["AT", "AE", "D", "S", "BE"]
var reversed = names.sorted( by: { $0 > $1 } )
print(reversed) //["S", "D", "BE", "AT", "AE"]
說(shuō)明:1表示閉包中第一個(gè)和第二個(gè)String類(lèi)型的參數(shù)。
如果你在閉包表達(dá)式中使用參數(shù)名稱(chēng)縮寫(xiě), 您可以在閉包參數(shù)列表中省略對(duì)其定義, 并且對(duì)應(yīng)參數(shù)名稱(chēng)縮寫(xiě)的類(lèi)型會(huì)通過(guò)函數(shù)類(lèi)型進(jìn)行推斷库快。in 關(guān)鍵字同樣也可以被省略摸袁。
運(yùn)算符函數(shù)
實(shí)際上還有一種更簡(jiǎn)短的方式來(lái)撰寫(xiě)上面例子中的閉包表達(dá)式。
Swift 的String類(lèi)型定義了關(guān)于大于號(hào) (>) 的字符串實(shí)現(xiàn)义屏,其作為一個(gè)函數(shù)接受兩個(gè)String類(lèi)型的參數(shù)并返回Bool類(lèi)型的值靠汁。 而這正好與sort(_:)方法的第二個(gè)參數(shù)需要的函數(shù)類(lèi)型相符合。 因此闽铐,您可以簡(jiǎn)單地傳遞一個(gè)大于號(hào)蝶怔,Swift可以自動(dòng)推斷出您想使用大于號(hào)的字符串函數(shù)實(shí)現(xiàn):
let names = ["AT", "AE", "D", "S", "BE"]
var reversed = names.sorted(by: >)
print(reversed)
尾隨閉包
尾隨閉包是一個(gè)書(shū)寫(xiě)在函數(shù)括號(hào)之后的閉包表達(dá)式,函數(shù)支持將其作為最后一個(gè)參數(shù)調(diào)用兄墅。
func someFunctionThatTakesAClosure(closure: () -> Void) {
// 函數(shù)體部分
}
// 以下是不使用尾隨閉包進(jìn)行函數(shù)調(diào)用
someFunctionThatTakesAClosure({
// 閉包主體部分
})
// 以下是使用尾隨閉包進(jìn)行函數(shù)調(diào)用
someFunctionThatTakesAClosure() {
// 閉包主體部分
}
let names = ["AT", "AE", "D", "S", "BE"]
//尾隨閉包
var reversed = names.sorted() { $0 > $1 }
print(reversed) //["S", "D", "BE", "AT", "AE"]
sort() 后的 { 1} 為尾隨閉包踢星。
注意: 如果函數(shù)只需要閉包表達(dá)式一個(gè)參數(shù),當(dāng)您使用尾隨閉包時(shí)隙咸,您甚至可以把()省略掉沐悦。
reversed = names.sorted { $0 > $1 }
捕獲值
閉包可以在其定義的上下文中捕獲常量或變量。
即使定義這些常量和變量的原域已經(jīng)不存在五督,閉包仍然可以在閉包函數(shù)體內(nèi)引用和修改這些值藏否。
Swift最簡(jiǎn)單的閉包形式是嵌套函數(shù),也就是定義在其他函數(shù)的函數(shù)體內(nèi)的函數(shù)充包。
嵌套函數(shù)可以捕獲其外部函數(shù)所有的參數(shù)以及定義的常量和變量秕岛。
func makeIncrementor(forIncrement amount: Int) -> () -> Int {
var runningTotal = 0
func incrementor() -> Int {
runningTotal += amount
return runningTotal
}
return incrementor
}
一個(gè)函數(shù)makeIncrementor ,它有一個(gè)Int型的參數(shù)amout, 并且它有一個(gè)外部參數(shù)名字forIncremet误证,意味著你調(diào)用的時(shí)候继薛,必須使用這個(gè)外部名字。返回值是一個(gè)()-> Int的函數(shù)愈捅。
函數(shù)題內(nèi)遏考,聲明了變量runningTotal 和一個(gè)函數(shù)incrementor。
incrementor函數(shù)并沒(méi)有獲取任何參數(shù)蓝谨,但是在函數(shù)體內(nèi)訪問(wèn)了runningTotal和amount變量灌具。這是因?yàn)槠渫ㄟ^(guò)捕獲在包含它的函數(shù)體內(nèi)已經(jīng)存在的runningTotal和amount變量而實(shí)現(xiàn)。
由于沒(méi)有修改amount變量譬巫,incrementor實(shí)際上捕獲并存儲(chǔ)了該變量的一個(gè)副本咖楣,而該副本隨著incrementor一同被存儲(chǔ)。
所以我們調(diào)用這個(gè)函數(shù)時(shí)會(huì)累加芦昔。
func makeIncrementor(forIncrement amount: Int) -> () -> Int {
var runningTotal = 0
func incrementor() -> Int {
runningTotal += amount
return runningTotal
}
return incrementor
}
let incrementByTen = makeIncrementor(forIncrement: 10)
// 返回的值為10
print(incrementByTen())
// 返回的值為20
print(incrementByTen())
// 返回的值為30
print(incrementByTen())
閉包是引用類(lèi)型
上面的例子中诱贿,incrementByTen是常量,但是這些常量指向的閉包仍然可以增加其捕獲的變量值。
這是因?yàn)楹瘮?shù)和閉包都是引用類(lèi)型珠十。
無(wú)論您將函數(shù)/閉包賦值給一個(gè)常量還是變量料扰,您實(shí)際上都是將常量/變量的值設(shè)置為對(duì)應(yīng)函數(shù)/閉包的引用。 上面的例子中焙蹭,incrementByTen指向閉包的引用是一個(gè)常量晒杈,而并非閉包內(nèi)容本身。
這也意味著如果您將閉包賦值給了兩個(gè)不同的常量/變量孔厉,兩個(gè)值都會(huì)指向同一個(gè)閉包拯钻。
func makeIncrementor(forIncrement amount: Int) -> () -> Int {
var runningTotal = 0
func incrementor() -> Int {
runningTotal += amount
return runningTotal
}
return incrementor
}
let incrementByTen = makeIncrementor(forIncrement: 10)
// 返回的值為10
incrementByTen()
// 返回的值為20
incrementByTen()
// 返回的值為30
incrementByTen()
// 返回的值為40
incrementByTen()
let alsoIncrementByTen = incrementByTen
// 返回的值也為50
print(alsoIncrementByTen())
====