Swift 函数和闭包

可变参数

可以设定同类型的参数为可变个数,然后在函数里将该参数作为数组来使用。 可变参数的位置不一定是最后一个。

示例代码:

func manyVar(v : Int..., d : Double) {
       for i in v {	//作为数组使用
                
	}
}
manyVar( d: 2.2) //传 0 个v参数
manyVar(v:1,2,3, d: 2.2) //传3个 v参数

闭包 和 函数 对外部变量的引用

Block 和 函数在使用它们外部的变量时,使用的是该变量的引用(无论是基本类型还是 类结构),当变量变化时,block和函数内部的该变量也会一起变化。

代码例子:

var bInt : Int = 4
func capture(_ num : Int) -> String {
        bInt += num
        return "caturpe \(bInt)"
    }
    bInt += 1
print("capture \(capture(1))”) //打印 capture 6
print("capture \(capture(2))) //打印 capture 7, 此时 bInt 变成7了

尾随闭包

当闭包作为函数最后一个参数时,可以将闭包体放在函数的括号外面,这是一个语法糖。

代码例子:

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

闭包的缩写

在闭包体内,可以用 $0 下标来获取对应的位置的参数。 代码例子:

let sort : (Int, Int) -> Bool = {   $0 > $1 }
[1,2,3].sorted(by: sort)

重载运算符

可以改写特定类型数据(对象)的运算符行为。

样例代码:

class EqualClass : Equatable {
    var value : Int = 2
    
    init(v : Int) {
        value = v
    }
    static func == (o1 : EqualClass, o2 : EqualClass) -> Bool  {
        return o1.value == o2.value
    }
    
    static func > (o1 : EqualClass, o2 : EqualClass) -> Bool {
        return o1.value > o2.value
    }
}

可逃逸闭包 @escaping

逃逸闭包:闭包有可能在函数结束后调用,闭包调用逃离了函数的作用域,需要通过@escaping声明。 比如下面例子,传入的闭包用对象属性保存了下来,可能在任意时间被调用。

class SwiftClosure : SwiftTestProtocol {
    typealias emptyClosure = () -> ()
    var callback :emptyClosure? = nil
    
    func setCallback(_ call : @escaping emptyClosure) {
        self.callback = call
    }
    
    func main() {
        self.setCallback {
            print("my callback")
        }
    }
}

逃逸闭包里不能使用外面的 inout 参数。

func modifyInt(_ value : inout Int) {
    self.setCallback { [weak self] in
            value += 4  //编译报错
            print("my callback")
        }
        self.callback!()
        self.callback!()
}