swift学习笔记二

一、函数
1.swift中函数可以当作别的函数的参数,也可以从其他函数中返回
函数的定义可以写在其他函数的定义中,可以在嵌套函数范围内实现功能的封装

2.多重返回值函数
可以用元组类型作为一个复合值从函数中返回,元组的成员不需要再元组从函数中返回时命名

func minMax(array: [Int]) -> (min: Int, max: Int) {
    var currentMin = array[0]
    var currentMax = array[0]
    for value in array[1.. currentMax {
            currentMax = value
        }
    }
    return (currentMin, currentMax)
}
print(minMax(array: [1, 3, 3, 5, 6]))
//打印结果 (1, 6)

上面的函数返回的元组可以时(min: Int, max: Int)? 类型

4.默认参数
在函数体中通过给参数赋值来为任意一个参数定义默认值,当默认值被定义后,调用这个函数时可以忽略这个参数。

func someFunction(parameterWithoutDefault: Int, parameterWithDefault: Int = 12) {
    print(parameterWithDefault,parameterWithoutDefault)
}
someFunction(parameterWithoutDefault: 10)
someFunction(parameterWithoutDefault: 8, parameterWithDefault: 6)

5.可变参数
一个函数最多只能拥有一个可变参数,一个可变参数可以接受零个或多个值,函数调用时,你可以用可变参数来制定函数参数可以被传入不确定数量的输入值,通过在变量类型名后面加入(...)的方式来定义可变参数

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)
// 返回 3.0, 是这 5 个数的平均数。
arithmeticMean(3, 8.25, 18.75)
// 返回 10.0, 是这 3 个数的平均数。

6.输入输出参数(函数参数默认时常量,在函数体内不能改变他的值)
输入输出参数不能又默认值,而且可变参数不能用inout标记

func swapTwoInts(_ a: inout Int, _ b: inout Int) {
    let temporaryA = a
    a = b
    b = temporaryA
}
var someInt = 3
var anotherInt = 107
swapTwoInts(&someInt, &anotherInt)
print("someInt is now \(someInt), and anotherInt is now \(anotherInt)")
// 打印 "someInt is now 107, and anotherInt is now 3"

7.函数的类型
函数的类型是由函数的参数类型和返回类型组成
(Int, Int) -> Int

8.函数类型作为参数类型

func printMathResult(_ mathFunction: (Int, Int) -> Int, _ a: Int, _b: Int) {
        print(mathFunction(a, b))
}
printMathResult(addTwoInts, 4, 6)

9.函数类型作为返回类型

func stepForward(_ input: Int) -> Int {
    return input + 1
}
func stepBackward(_ input: Int) -> Int {
    return input - 1
}
func chooseStepFunction(backward: Bool) -> (Int) -> Int {
    return backward ? stepBackward : stepForward
}
var currentValue = 3
let moveNearerToZero = chooseStepFunction(backward: currentValue > 0)
// moveNearerToZero 现在指向 stepBackward() 函数。
print("Counting to zero:")
// Counting to zero:
while currentValue != 0 {
    print("\(currentValue)... ")
    currentValue = moveNearerToZero(currentValue)
}
print("zero!")
// 3...
// 2...
// 1...
// zero!

10.嵌套函数
可以把函数定义在别的函数体中,默认情况在外部是不能调用的,但是可以作为返回值返回

二、闭包
1.函数时特殊的闭包
全局函数是一个有名字但不会捕获任何值的函数
嵌套函数是有名字并可以捕获其封闭函数域内值的闭包

swift的闭包表达式拥有简洁的风格,并鼓励在场景中进行语法优化:
利用上下文推断参数和返回值类型
隐式表达单表达式闭包,即但表达式闭包可以隐藏return关键字
参数名称缩写
尾随闭包语法

2.闭包表达式语法

{ (parameters) -> returnType in
        statements
}

闭包的参数可以是 in-out参数,但不能设定默认值。也可以使用具名的可变参数,元组也可以作为参数和返回值

3.尾随闭包
如果你需要将一个很长的闭包表达式作为最后一个参数传递给函数,可以使用尾随闭包来增强函数的可读性。尾随闭包是一个书写在函数括号之后的闭包表达式,函数支持将其作为最后一个参数调用。在使用尾随闭包的时候,你不用写出他的参数标签

func someFunctionThatTakesAClosure(closure: () -> Void) {
    // 函数体部分
}

// 以下是不使用尾随闭包进行函数调用
someFunctionThatTakesAClosure(closure: {
    // 闭包主体部分
})

// 以下是使用尾随闭包进行函数调用
someFunctionThatTakesAClosure() {
    // 闭包主体部分
}

如果闭包表达式是函数或方法的唯一参数,甚至可以把函数后面的()省略

 someFunctionThatTakesAClosure{
      // 闭包主体部分
}

4.值捕获
闭包可以在其定义的上下文中捕获常量或者变量,即使这些常量或者变量的原作用域已经不存在,闭包仍然可以在闭包函数体内引用和修改这些值。

5.闭包是引用类型
函数和闭包都是引用类型

6.逃逸闭包
当一个闭包作为一个参数传到一个函数中,但是这个闭包在函数返回之后才能执行,我们称该闭包从函数中逃逸,定义此类型的闭包的时候,在闭包前面添加关键字@escaping,用来指明这个表是允许逃逸出这个函数的。

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

someFunctionWithEscapingClosure(_:)函数接受一个闭包作为参数,该闭包被添加到函数外定义的数组中,如果不添加@escaping 编译就会报错

将一个闭包标记为@escaping 意味着必须在闭包中显示的引用self

func someFunctionWithNonescapingClosure(closure: () -> Void) {
    closure()
}

class SomeClass {
    var x = 10
    func doSomething() {
        someFunctionWithEscapingClosure { self.x = 100 }
        someFunctionWithNonescapingClosure { x = 200 }
    }
}

let instance = SomeClass()
instance.doSomething()
print(instance.x)
// 打印出 "200"

completionHandlers.first?()
print(instance.x)
// 打印出 "100"

7.自动闭包
自动闭包能让你延迟求值,因为知道你调用这个闭包,代码段才会执行

var customersInLine = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
print(customersInLine.count)
// 打印出 "5"

let customerProvider = { customersInLine.remove(at: 0) }
print(customersInLine.count)
// 打印出 "5"

print("Now serving \(customerProvider())!")
// Prints "Now serving Chris!"
print(customersInLine.count)
// 打印出 "4"

customerProvider的类型不是String 而是一个没有参数返回值为String的函数

将闭包作为参数传递给函数

// customersInLine is ["Alex", "Ewa", "Barry", "Daniella"]
func serve(customer customerProvider: () -> String) {
    print("Now serving \(customerProvider())!")
}
serve(customer: { customersInLine.remove(at: 0) } )
// 打印出 "Now serving Alex!"

上面的 serve(customer:)
函数接受一个返回顾客名字的显式的闭包。下面这个版本的 serve(customer:)完成了相同的操作,不过它并没有接受一个显式的闭包,而是通过将参数标记为 @autoclosure来接收一个自动闭包。现在你可以将该函数当作接受 String 类型参数(而非闭包)的函数来调用。customerProvider参数将自动转化为一个闭包,因为该参数被标记了 @autoclosure特性。

// customersInLine is ["Ewa", "Barry", "Daniella"]
func serve(customer customerProvider: @autoclosure () -> String) {
    print("Now serving \(customerProvider())!")
}
serve(customer: customersInLine.remove(at: 0))
// 打印 "Now serving Ewa!"

你可能感兴趣的:(swift学习笔记二)