📜  Swift 闭包(1)

📅  最后修改于: 2023-12-03 15:05:26.267000             🧑  作者: Mango

Swift 闭包

在 Swift 中,闭包是一种高级函数的形式,它可以像变量一样传递和处理。本文将介绍 Swift 中闭包的基本概念和使用方法。

闭包是什么?

闭包在 Swift 中也有函数类型的特性,它们不需要名称和标记,可以使用常规函数完全完成的任务。闭包内嵌在函数或方法中,可以通过定义和传递其内部变量来访问函数或方法的作用域。

闭包由花括号 {} 包围,可以接受零个或多个参数,以及可选的返回类型。一个简单的闭包可以看起来像这样:

{ (parameters) -> ReturnType in
    // Code
}

其中 parameters 是闭包的参数,ReturnType 是闭包的返回类型,Code 是执行的代码。一个没有参数并返回一个整数的闭包可以写成:

{ () -> Int in
    return 42
}

这个闭包可以保存并调用,如下所示:

let closure = { () -> Int in
    return 42
}

let result = closure()
print(result) // 输出: 42

请注意,闭包名称 closure 只是一个常量,用于存储闭包本身,它本身不是一个调用闭包的方法。

简化闭包

使用 Swift 中的某些简化技术可以进一步简化闭包的语法。

参数类型和返回类型的省略

由于 Swift 编辑器是一个先进的类型推论器,可以根据上下文自动推断类型,因此不需要在闭包中明确指定参数类型和返回类型。以下是一个不到返回类型的简化闭包:

{ (parameters) in
    // Code
}

如果闭包不返回任何内容,则可以完全省略返回类型。以下是一个省略了参数类型和返回类型的最终版本:

{ parameters in
    // Code that doesn't return anything
}

对于参数数量为零的闭包,可以进一步简化:

{
    // Code that doesn't accept any parameters
}
箭头函数的省略

因为多数时间你的闭包只用于一行代码,所以 Swift 提供了省略的写法:

{ parameters in code }

如果只需要使用闭包,而不需要将其存储为变量或常量,则可以利用尾随闭包语法。以下是使用普通闭包:

func performAction(closure: () -> ()) {
    // Perform action before closure
    closure()
}

performAction({
    // Closure code
})

以下是使用尾随闭包的相应代码:

performAction() {
    // Closure code
}
捕获变量

闭包与内部作用域中的变量共存,可以访问其上下文中的变量。这个概念叫做捕获变量。在下面的示例中,我将创建一个计数器函数,该函数返回一个闭包,该闭包每次被调用时都会递增计数器计数。

func counter() -> (() -> Int) {
    var count = 0
    func increment() -> Int {
        count += 1
        return count
    }
    return increment
}
let counter1 = counter()
let counter2 = counter()

print(counter1()) // Print 1
print(counter1()) // Print 2
print(counter2()) // Print 1
print(counter1()) // Print 3
print(counter2()) // Print 2

请注意,每个捕获变量都是闭包内的一个本地变量,而不是外部变量的引用。因此,闭包的状态在所有复制中都是独立的。

高级用法

除了上面介绍的基础用法之外,闭包还具有其他高级功能。

在数组中映射和排序

数组映射和排序方法通常使用闭包来执行其计算。以下示例使用 map() 函数将所有字符串转换为大写字母:

let arr = ["apple", "banana", "pear", "grape"]
let uppercaseArr = arr.map { $0.uppercased() }

print(uppercaseArr) // 输出: ["APPLE", "BANANA", "PEAR", "GRAPE"]

以下是使用排序功能的示例:

let arr = ["apple", "Banana", "pear", "Grape"]
let sortedArr = arr.sorted { $0.uppercased() < $1.uppercased() }

print(sortedArr) // 输出: ["apple", "Banana", "Grape", "pear"]
延迟初始化

使用闭包可以使项目中的变量在首次访问时进行延迟初始化。这可能是某些情况下有用的,如当变量初始化需要长时间计算或需要其他组件完成先前的初始化时。

class SomeClass {
    var someVariable: String = {
        var computedVariable = "Hello "
        computedVariable += "World!"
        return computedVariable
    }()
}

let instanceOfSomeClass = SomeClass()
print(instanceOfSomeClass.someVariable) // 输出: Hello World!

这里的 someVariable 变量使用递推闭包进行延迟初始化。通过将闭包作为 someVariable 的默认值传递,我们可以确保只有第一次访问 someVariable 时才会生成字符串 "Hello World!"。

结论

Swift 中的闭包为开发人员提供了一种灵活且强大的方法来表示函数,并可以使用变量和常量传递和处理它们。使用闭包可以使代码更短、更具可读性和可维护性。您可以使用闭包映射和排序数组,也可以使用它们为变量进行延迟初始化。