Swift学习之闭包

一、闭包表达式

在Swift中,可以通过func定义一个函数。也可以通过闭包表达式定义一个函数

func test(v1:Int,v2:Int) ->Int {
    return v1 + v2;
}
-----------------------------------------------------------------------
let fn =   {
            (v1:Int,v2:Int) ->Int in
            return v1 + v2;
           }
print(fn(10,20));
  • 闭包表达式语法基本形式
  { (parameters) -> (return type) in
    statements
  }

闭包的函数整体部分由关键字 in 导入,这个关键字表示闭包的形式参数类型和返回类型定义已经完成,并且闭包的函数体即将开始。

  • 定义一个闭包表达式
let fn =   {
            (v1:Int,v2:Int) ->Int in
            return v1 + v2;
           }
print(fn(10,20));
import UIKit
class Student{
    func test(){
        {
            (v1:Int,v2:Int) ->Int in
            
            print("闭包表达式")
            return v1 + v2;
        }(10,20)
    }
}
let s = Student()
s.test()
  • 闭包表达式的类型
    闭包表达式本质是函数,其类型和函数的类型一样。可分为: () -> (),(Int) -> (),(Int) -> (Int),() -> (Int) ······等

二、闭包表达式作为参数传递

- (void)execWithFn:( NSInteger (^)(NSInteger, NSInteger))fn{
    fn(10,20);
}

oc中block可以作为函数的参数进行传递,swift中闭包当然也可以作为函数的参数进行传递

class Student{
    func exec(fn: (Int,Int) -> Int) {
       print(fn(1,2))
    }
}
let s = Student()
s.exec (fn: { (v1:Int, V2:Int) -> Int in
    print("闭包")
    return v1 + V2
})
class Student{
    func exec(a:Int,b:Int,fn: (Int,Int) -> Int,c:Int) {
       print(fn(1,2))
    }
}

let s = Student()
s.exec (a:10,b:20,fn: { (v1:Int, V2:Int) -> Int in
    print("闭包")
    return v1 + V2
},c:21)

三、尾随闭包

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

class Student{
    func exec(a:Int,b:Int,fn: (Int,Int) -> Int) {
       print(fn(1,2))
    }
}
let s = Student()

//未使用尾随闭包
s.exec (a:10,b:20,fn: { (v1:Int, V2:Int) -> Int in
    print("未使用尾随闭包")
    return v1 + V2
})

//使用了尾随闭包
s.exec (a: 10, b: 20){ (c:Int, d:Int) -> Int in
    print("使用了尾随闭包")
    return c + d
}
  • 如果闭包是函数的最后一个参数,则可以将闭包写在()后面,这种写法就是尾随闭包。

class Student{
    func exec(fn:(Int,Int) -> Int) {
       print(fn(1,2))
    }
}
let s = Student()
s.exec { (c:Int, d:Int) -> Int in
    return c + d
}
  • 如果闭包表达式是函数的唯一实参,而且使用了尾随的语法,那就可以省略函数名后的圆括号。

四、自动闭包

官方解释:自动闭包是一种自动创建的用来把作为实际参数传递给函数的表达式打包的闭包。它不接受任何实际参数,并且当它被调用时,它会返回内部打包的表达式的值。这个语法的好处在于通过写普通表达式代替显式闭包而使你省略包围函数形式参数的括号。

func test(wage:Int,fn:()->(Int)){
    if wage<5000 {
      
        print("不用交税")
    }else{
        print("\(fn())元要交税")
    }
}

var wage = 8000
test(wage: wage){
  return (wage-5000)
}

wage = 2000
test(wage: wage){
    return (wage-5000)
}

以上代码的意思是,当wage = 8000,需要交wage-5000的税,而wage =2000,不需要交税。不需要交税我们就不必去计算wage-5000。我们设计 test函数中计算税的表达式为一个闭包参数,这样就可以在需要的时候执行,提高了效率。

以上是正常的闭包定义和调用,如果我们使用了自动闭包

func test(wage:Int,fn:@autoclosure()->(Int)){
    if wage<5000 {
      
        print("不用交税")
    }else{
        print("\(fn())元要交税")
    }
}
var wage = 8000
test(wage: wage,fn: wage-5000)

wage = 2000
test(wage:wage, fn:wage-5000)

wag-5000是一个整数运算表达式,却能传递给类型为闭包的参数fn,很惊喜吧。这是@autoclosure标记后,test(wage: wage,fn: wage-5000)虽然fn表面上看传递的是wage-5000,编译器会自动把传递的表达式加上{},从而转换为闭包{wage-5000}。也就是最终的调用是test(wage: wage,fn: {wage-5000})。这就是自动闭包吧。我们这时再去看官方的解释,也许就会理解它所表达的意思。

  • @autoclosure 会自动将 20 封装成闭包 { 20 }
  • @autoclosure 只支持 () -> T 格式的参数
  • @autoclosure 并非只支持最后1个参数
  • 空合并运算符 ?? 使用了 @autoclosure 技术
  • 有@autoclosure、无@autoclosure,构成了函数重载

五、逃逸闭包

逃逸闭包、非逃逸闭包,一般都是当作参数传递。

1、非逃逸闭包

func test(_ fn:(Int,Int) -> Int){
    fn(1,2)
}

 test ({ (v1:Int, v2:Int) -> Int in
    v1 + v2
})

闭包fn的调用是在test函数作用域内,发生在 函数结束前。这就是非逃逸闭包

2、逃逸闭包

import UIKit

class Person {
var testFn:(Int,Int) ->Int

    init(fn:@escaping (Int,Int)->Int) {
        self.testFn = fn
    }
    
}

var p = Person(fn:
           {
            
            (v1:Int,v2:Int) in
            
             v1 + v2 
          
           }
)
print(p.testFn(1,2))

闭包fn的调用不是直接在函数内调用,而是在init函数外调用,闭包调用了逃离了函数的作用域,这就是逃逸闭包。需要用@escapings声明

  • 非逃逸闭包:闭包的调用发生在函数结束前,闭包调用在函数作用域内
    -逃逸闭包:闭包有可能在函数结束后调用,闭包调用逃离了函数的作用域

六、闭包

一个函数和它所捕获 的变量\常量组合起来,称之为 闭包

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 闭包引入 计算1个数的平方 函数写法 闭包写法 闭包含义 闭包是可以被传递和引用的一个独立模块 闭包能够捕获和存储...
    YungFan阅读 2,066评论 0 17
  • 闭包的介绍 闭包和OC中的block非常相似 OC中的block是匿名的函数 Swift中的闭包是一个特殊的函数 ...
    CoderLWG阅读 229评论 0 0
  • 闭包是自包含的函数代码块,可以在代码中被传递和使用。Swift 中的闭包与 C 和 Objective-C 中的代...
    雨影阅读 729评论 0 2
  • 本章将会介绍 闭包表达式尾随闭包值捕获闭包是引用类型逃逸闭包自动闭包枚举语法使用Switch语句匹配枚举值关联值原...
    寒桥阅读 1,577评论 0 3
  • swift中闭包类似于oc中的Block语句块 一、一个最简单的闭包实现 🌰1 闭包就是写好的一段代码,然后在某一...
    巧克力的qiao阅读 301评论 0 2