《Swift学习笔记》10 - 闭包的简单介绍

2019-08-11  本文已影响0人  ShIwEn9

介绍:Swift 语言由苹果公司在 2014 年推出,用来撰写 Mac OS 和 iOS 应用程序,并且Swift还是开源的,开源地址:https://github.com/apple/swift,同时附上官方博客地址:https://swift.org
目前Swift已经发展到了第五版本。显然苹果大有推翻 OC “江山”的意思.
今天就来初探一下Swift,看看究竟为何swift有这么大的能力。
参考内容:
Swift中文
YungFan老师

swift
一、闭包的介绍
  1. 闭包的含义
  1. 闭包的书写
// 基本书写方式
 { (parameters) -> (return type) in
    statements
  }

// 案例
{
    (闭包的形式参数: String) -> String in
    return 闭包的形式参数
}
二、闭包主要知识点
  1. 参数名称缩写

闭包的正常使用

//从数组中筛选指出合适的数据组成新的数组
let block = {
    (oneNum : Int) -> Bool in
    return oneNum > 10
}

print(block(11)) // true

第一种简写方法:通过类型推倒
返回箭头 ( ->)围绕在形式参数名周围的括号()都可以省略

let blockTwo = {oneNum in return oneNum>10}
print(blockTwo(3)) // false

第二种:闭包的隐式返回 ,省略return关键字

let blockThree = {numOne in numOne>10}
print(blockThree(12)) // true

第三种简写:参数名称缩写,省略参数声明和in,改为$0
Swift 自动对行内闭包提供简写实际参数名,你也可以通过 0 ,1 , $2 等名字来引用闭包的实际参数值。
in关键字也能被省略,因为闭包表达式完全由它的函数体组成.

let blockFour = {$0>10}
print(blockFour(8)) // false

可以看到 $0代替了 上面的numOne,并且可以in给隐藏了

三、尾随闭包
如果你需要将一个闭包表达式作为函数最后一个实际参数传递给函数,使用尾随闭包将增强函数的可读性。尾随闭包是一个被书写在函数形式参数的括号外面(后面)的闭包表达式:

func doSomething(name: String, block:(_:String)->Void){
    block("尾随闭包 name=" + name)
}

let age = "24"

doSomething(name: "Swift") { (age) in
    print(age)
}

doSomething(name: "Swift", block: {s in print(s)})

四、捕获值

func makeIncrementer(forIncrement amount: Int) -> () -> Int {
    var runningTotal = 0
    func incrementer() -> Int {
        runningTotal += amount
        return runningTotal
    }
    return incrementer
}
//这个例子定义了一个叫 incrementByTen 的常量,该常量指向一个每次调用会加 10 的函数。调用这个函数多次得到以下结果:
let incrementByTen = makeIncrementer(forIncrement: 10)
incrementByTen() // 返回的值为10
incrementByTen() // 返回的值为20
incrementByTen() // 返回的值为30

如果你建立了第二个 incrementer ,它将会有一个新的、独立的 runningTotal变量的引用:

let incrementBySeven = makeIncrementer(forIncrement: 7)
incrementBySeven()
// 返回的值为  7

再次调用原来增量器 ( incrementByTen ) 继续增加它自己的变量 runningTotal 的值,并且不会影响 incrementBySeven 捕获的变量 runningTotal 值:

incrementByTen() // 返回的值为  40

五、逃逸闭包

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

函数 someFunctionWithEscapingClosure(_:) 接收一个闭包作为实际参数并且添加它到声明在函数外部的数组里。如果你不标记函数的形式参数为 @escaping ,你就会遇到编译时错误。

让闭包 @escaping 意味着你必须在闭包中显式地引用self ,比如说,下面的代码中,传给someFunctionWithEscapingClosure(_:)的闭包是一个逃逸闭包,也就是说它需要显式地引用 self 。相反,传给 someFunctionWithNonescapingClosure(_:) 的闭包是非逃逸闭包,也就是说它可以隐式地引用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)
// Prints "200"
 
completionHandlers.first?()
print(instance.x)
// Prints "100"

六、自动闭包

下面的代码展示了闭包如何延迟求值。

var customersInLine = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
print(customersInLine.count)
// Prints "5"
 
let customerProvider = { customersInLine.remove(at: 0) }
print(customersInLine.count)
// Prints "5"
 
print("Now serving \(customerProvider())!")
// Prints "Now serving Chris!"
print(customersInLine.count)
// Prints "4"

当你传一个闭包作为实际参数到函数的时候,你会得到与延迟处理相同的行为。

// customersInLine is ["Alex", "Ewa", "Barry", "Daniella"]
func serve(customer customerProvider: () -> String) {
    print("Now serving \(customerProvider())!")
}
serve(customer: { customersInLine.remove(at: 0) } )
// Prints "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))
// Prints "Now serving Ewa!"
// customersInLine is ["Barry", "Daniella"]
var customerProviders: [() -> String] = []
func collectCustomerProviders(_ customerProvider: @autoclosure @escaping () -> String) {
    customerProviders.append(customerProvider)
}
collectCustomerProviders(customersInLine.remove(at: 0))
collectCustomerProviders(customersInLine.remove(at: 0))
 
print("Collected \(customerProviders.count) closures.")
// Prints "Collected 2 closures."
for customerProvider in customerProviders {
    print("Now serving \(customerProvider())!")
}
// Prints "Now serving Barry!"
// Prints "Now serving Daniella!"

闭包的介绍就到这里了。有什么不足的地方欢迎补充。文章大多数内容来自:

Swift中文
YungFan老师
再次感谢!

求职广告:本人实习生,现在急需一份工作,杭州南京合肥的都可以。对我感兴趣的可以私聊我 0.0。谢谢~~~

上一篇下一篇

猜你喜欢

热点阅读