函數(shù)
定義:函數(shù)是執(zhí)行特定任務的自包含代碼塊忆蚀。(Swift中每個函數(shù)都有一個類型,由函數(shù)的參數(shù)類型和返回類型組成)姑裂。
使用:
-
函數(shù)可以返回元組(也可以是可選元組:整個元組是可選的馋袜,而不僅僅是元組中的每個單獨的值)
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] { if value < currentMin { currentMin = value } else if value > currentMax { currentMax = value } } return (currentMin, currentMax) }
-
使用外部參數(shù)和內(nèi)部參數(shù),外部參數(shù)可以用“_”省略
func greet(Person person: String, _ hometown: String) -> String { return "Hello \(person)! Glad you could visit from \(hometown)." } print(greet(Person: "Bill", "Cupertino")) // Prints "Hello Bill! Glad you could visit from Cupertino."
-
使用默認參數(shù)值舶斧,調(diào)用該函數(shù)時可以省略該參數(shù)
func someFunction(parameterWithoutDefault: Int, parameterWithDefault: Int = 12) { // If you omit the second argument when calling this function, then // the value of parameterWithDefault is 12 inside the function body. } someFunction(parameterWithoutDefault: 3, parameterWithDefault: 6) // parameterWithDefault is 6 someFunction(parameterWithoutDefault: 4) // parameterWithDefault is 12
使用變量參數(shù)欣鳖,則此參數(shù)可以接受0-N的參數(shù)值,函數(shù)內(nèi)部茴厉,此參數(shù)當做函數(shù)處理泽台,關鍵字"..."(注:函數(shù)最多有一個可變參數(shù))
func arithmeticMean(_ numbers: Double...) -> Double {
var total: Double = 0
for number in numbers {
total += number
}
return total / Double(numbers.count)
}
arithmeticMean(1, 2, 3, 4, 5)
// returns 3.0, which is the arithmetic mean of these five numbers
arithmeticMean(3, 8.25, 18.75)
// returns 10.0, which is the arithmetic mean of these three numbers
-
in-Out參數(shù)什荣,函數(shù)參數(shù)類型默認是let類型,不可更改怀酷,若需要更改參數(shù)稻爬,則在參數(shù)類型前加上關鍵字
inout
。(注意:in-Out參數(shù)不能具有默認值胰坟,并且可變參數(shù)不能標記為inout)func swapTwoInts(_ a: inout Int, _ b: inout Int) { (a,b) = (b,a) //交換兩個值 } //調(diào)用方式如下: var someInt = 3 var anotherInt = 107 swapTwoInts(&someInt, &anotherInt) print("someInt is now \(someInt), and anotherInt is now \(anotherInt)") // Prints "someInt is now 107, and anotherInt is now 3"
-
函數(shù)類型:函數(shù)參數(shù)類型和返回值類型的組合
該函數(shù)的類型是(Int, Int) -> Int因篇,并返回Int泞辐。 func addTwoInts(_ a: Int, _ b: Int) -> Int { return a + b } 該函數(shù)的類型是() -> Void或“沒有參數(shù)的函數(shù)笔横,并返回” Void。 func printHelloWorld() { print("hello, world") }
函數(shù)類型可用作:函數(shù)參數(shù)類型咐吼,返回值類型等
-
函數(shù)嵌套:可以在函數(shù)內(nèi)部定義其他函數(shù)
//不推薦:一般一個函數(shù)就完成一個功能模塊 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 }
閉包
-
表達式一般形式
{(參數(shù)) -> 返回類型 in 聲明 }
-
幾種閉包的使用方式舉例:
//完整格式: reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in return s1 > s2 }) //省略參數(shù)類型:因為swift具有上下文自動推斷數(shù)據(jù)格式 reversedNames = names.sorted(by: { s1, s2 in return s1 > s2 } ) //閉包中只有一條語句時吹缔,稱為隱式返回,即省略return reversedNames = names.sorted(by: { s1, s2 in s1 > s2 } ) //最簡格式:使用參數(shù)值$0锯茄,$1厢塘,$2依次代替參數(shù)值 reversedNames = names.sorted(by: { $0 > $1 } ) //追尾閉包:既閉包類型作為函數(shù)參數(shù)的最后一個參數(shù) func someFunctionThatTakesAClosure(closure: () -> Void) { // function body goes here } 調(diào)用時可以寫成如下格式: someFunctionThatTakesAClosure(closure: { // closure's body goes here })
逃逸閉包:逃逸閉包恰恰與非逃逸閉包相反,其生命周期長于相關函數(shù)肌幽,當函數(shù)退出的時候晚碾,逃逸閉包的引用仍然被其他對象持有,不會在相關函數(shù)結(jié)束后釋放喂急。
-
非逃逸閉包(默認):1. 把閉包作為參數(shù)傳遞給函數(shù)格嘁。2. 函數(shù)中運行該閉包。3. 退出函數(shù)廊移。
class SomeClass { var x = 10 func doSomething() { someFunctionWithEscapingClosure { self.x = 100 } //逃逸閉包(不能直接寫x) someFunctionWithNonescapingClosure { x = 200 } //非逃逸閉包(可以直接引用) } }
-
自動閉包(
@autoclosure
):是一種自動創(chuàng)建的用來把作為實際參數(shù)傳遞給函數(shù)的表達式打包的閉包糕簿。- 要求:它不接受任何實際參數(shù)
- 表現(xiàn):它被調(diào)用時,它會返回內(nèi)部打包的表達式的值
- 好處:在于通過寫普通表達式代替顯式閉包而使你省略包圍函數(shù)形式參數(shù)的括號
func testB() { let neStr = self.testbBlock1(block: "2sssssss") self.testBlock2(block: (print("ffjfjfjjf"))) print(neStr) } func testbBlock1(block: @autoclosure ()->String) -> String { return block() } func testBlock2(block:@autoclosure ()->()) { block() }
枚舉
-
枚舉語法
enum 枚舉名 { case 枚舉值1 case 枚舉值2 .... } //注意: 1. 枚舉名應遵循首字母大寫的駝峰式復數(shù)命名 2. 每個枚舉值沒有默認的0狡孔,1懂诗,2...等值 //可以攜帶參數(shù) enum Barcode { case upc(Int, Int) case qrCode(String) } var productBarcode = Barcode.qrCode("ABCED") switch productBarcode { //如果所有關聯(lián)值被提取為常量或變量,則可以將var或let注釋放在枚舉值前面苗膝,如下: case let .upc(number1,number2) : print("\(number1)") case.qr(let code): print("\(code)") } //Prints:ABCED
-
原始值:可以是字符串殃恒、字符、任意的整數(shù)或浮點數(shù)類型辱揭,但是原始值是唯一的芋类。
enum Plant: Int { case mercury = 1,venus,earth } print("\(Plant.earth.rawValue)") == 3
-
初始化值:如果你使用原始值定義枚舉,則枚舉將自動接收一個初始化器界阁。
//possiblePlanet 為 venus let possiblePlanet = Planet(rawValue: 2)
-
遞歸枚舉:簡單理解為自己調(diào)用自己侯繁,而遞歸枚舉并不是函數(shù),它并不執(zhí)行某項運算泡躯,他只是表達一個數(shù)據(jù)或者一種表達式贮竟。(關鍵字:indirect:表示可以遞歸)丽焊,整個enum都可以遞歸就在enum前加上關鍵字:indirect
enum ArithmeticExpression { case number(Int) //indirect:為遞歸枚舉的關鍵字 indirect case addition(ArithmeticExpression, ArithmeticExpression) indirect case multiplication(ArithmeticExpression, ArithmeticExpression) } let five = ArithmeticExpression.number(5) let four = ArithmeticExpression.number(4) let sum = ArithmeticExpression.addition(five, four) //并沒有真正執(zhí)行運算 let product = ArithmeticExpression.multiplication(sum, ArithmeticExpression.number(2)) 實現(xiàn)遞歸枚舉的最好方式就是用遞歸函數(shù): func evaluate(_ expression: ArithmeticExpression) -> Int { switch expression { case let .number(value): return value case let .addition(left, right): return evaluate(left) + evaluate(right) case let .multiplication(left, right): return evaluate(left) * evaluate(right) } } print(evaluate(product)) // Prints "18"
類和結(jié)構體
- 相同點:
- 定義屬性以存儲值
- 定義提供功能的方法
- 定義下標語法提供對其值得訪問
- 定義初始化器以設置其默認實現(xiàn)
- 擴展其功能
- 遵守協(xié)議以提供某種特定的標準功能
- 不同點:
- 類可以被繼承
- 類型轉(zhuǎn)換使您能夠在運行時檢查和解釋類實例的類型。
- 取消初始化使類的實例可以釋放其分配的任何資源咕别。
- 引用計數(shù)允許多個對類實例的引用技健。
- 判斷是否是同類:(===)(!==)比較兩個類對象是否相等
- 當結(jié)構體對象為let類型時,不管屬性是var或let都不能修改屬性的值惰拱,類則不同雌贱。能否修改由屬性的類型決定
屬性
-
存儲屬性:是存儲在特定類或結(jié)構體實例里的一個常量或變量,只能用于類和結(jié)構體
var firstValue: Int let secondValue: Int
-
計算屬性:不直接存儲值偿短,而是提供一個getter和一個可選的setter方法欣孤,來間接和設置其他屬性或變量的值,可以用于類昔逗、結(jié)構體和枚舉
struct AlternativeRect { var origin = Point() var size = Size() var center: Point { //計算屬性 get { //只讀屬性時可以不寫get降传,直接返回 let centerX = origin.x + (size.width / 2) let centerY = origin.y + (size.height / 2) return Point(x: centerX, y: centerY) } set { //沒有set則為只讀計算屬性 origin.x = newValue.x - (size.width / 2) origin.y = newValue.y - (size.height / 2) } } }
-
lazy屬性:指的是第一次被調(diào)用的時候才會計算其初始值的屬性。
注意:lazy屬性必須聲明為變量var勾怒,因為屬性的初始值可能在實例構造完成之后才會得到婆排,而常量屬性在構造過程之前必須要有初始值。
注意:如果一個被標記為lazy的屬性在沒有初始值時就同時被多個線程訪問笔链,則無法保證該屬性只會被初始化一次段只。
-
格式
lazy var 屬性名:屬性類型 = {調(diào)用一個沒有參數(shù),返回值是當前屬性類型的閉包鉴扫。 閉包中需要創(chuàng)建一個當前屬性的變量返回}()
-
類型屬性:無論創(chuàng)建多少個該類型的實例赞枕,這些屬性都是唯一共享的一份。(static關鍵字)
- 注意:1. 必須給存儲類型屬性指定默認值幔妨,因為類型本身沒有構造器鹦赎。
- 存儲型類型屬性時演示初始化的,它們只有在第一次被訪問的時候才會被初始化误堡。即不需要lazy關鍵字修飾古话。
- 在類中可以使用
class
替代static
來支持子類對父類的實現(xiàn)進行重寫。
- 在類中可以使用
-
類型屬性是通過類型本身來訪問锁施,而不是通過實例陪踩。
class SomeClass { static var storedTypeProperty = "Some value." static var computedTypeProperty: Int { return 27 } class var overrideableComputedTypeProperty: Int { return 107 } }
-
-
屬性觀察器:
- willSet -- 在值被存儲之前被調(diào)用,可以再此名稱后加(變量名),默認參數(shù)是newValue,此值就代表將要賦的值悉抵。
- didSet -- 在存儲值之前被調(diào)用肩狂,可以再此名稱后加(變量名),默認參數(shù)是oldValue,此值就代表原始值。
方法
方法:實現(xiàn)一定功能的函數(shù)姥饰。類傻谁、結(jié)構體和枚舉中都能定義方法。
-
注意:結(jié)構體和枚舉是值類型列粪。默認情況下审磁,不能從實例方法中修改值類型的屬性谈飒,若想要修改其屬性值,必須在方法
func
前添加mutating
關鍵字态蒂。struct Point { var x = 0.0, y = 0.0 mutating func moveBy(x deltaX: Double, y deltaY: Double) { x += deltaX y += deltaY } } 等同于下面: struct Point { var x = 0.0, y = 0.0 mutating func moveBy(x deltaX: Double, y deltaY: Double) { self = Point(x: x + deltaX, y: y + deltaY) } } //突變的方法 enum TriStateSwitch { case off, low, high mutating func next() { switch self { case .off: self = .low case .low: self = .high case .high: self = .off } } }
-
類型方法和屬性方法
- 類型屬性需要通過類型名來獲取杭措,通過變量或?qū)ο笕カ@取的話是找不到該屬性的
- 類型屬性必須有初值,同時不能直接再構造函數(shù)中初始化钾恢,需要通過結(jié)構體名或類名去調(diào)用賦值
- 類型方法——
- 在類中可以使用class關鍵字代替static
- 類型方法中不可以使用變量型屬性
- 類型方法中不可以調(diào)用變量型方法
- 變量型方法和類型方法可以同名
- 總結(jié):變量和類型之間都不能互相調(diào)用