Swift学习笔记七:闭包

闭包可以 捕获 和存储其所在上下文中任意常量和变量的引用。 Swift 会为您管理在 捕获 过程中涉及到的内存操作。

在 函数 章节中介绍的全局和嵌套函数实际上也是特殊的闭包,闭包采取如下三种形式之一:

1. 全局函数是一个有名字但不会捕获任何值的闭包

2. 嵌套函数是一个有名字并可以捕获其封闭函数域内值的闭包

3. 闭包表达式是一个可以捕获其上下文中变量或常量值的没有名字的闭包

一、闭包表达式

闭包函数类似于Objective-C中的block。下面我们用事实说话:

let counts = [3,2,5,1,6]
//********** 方法1:使用普通函数*******
func sortInc(item1:Int,item2:Int) ->Bool{
    return item1 < item2
}
sort(counts, sortInc)
//********** 方法2:使用闭包函数*******
sort(counts, {(a:Int,b:Int) -> Bool in return a<b})

Swift 标准库提供了 sort 函数,会根据您提供的排序闭包将已知类型数组中的值进行排序。

方法1中使用的是普通函数,方法2传入的是一个闭包,在这里,这2个方法最终的效果是一样的。但是明显的,方法2写起来比方法1要简单

1)闭包表达式语法

{ (parameters) -> returnType in      statements  }  

关键:闭包表达式主要分为3个部分

①闭包表达式所有内容都由大括号{}括起来

②闭包表达式关键字in前面部分和函数的定义是一样的。只是去掉了func和函数名

③闭包表达式关键字in后面部分是函数的具体代码

2) 根据上下文推断类型

因为排序闭包是作为函数的参数进行传入的,Swift可以推断其参数和返回值的类型。上面的方法2中的代码可以改为下面的形式:

sort(counts,
{a,b in
return a<b})

3)单一表达式闭包可以省略 return

单一表达式闭包可以通过隐藏 return 关键字来隐式返回单行表达式的结果。上面的代码还可以省略:

sort(counts,
{a,b in a<b})

这个例子中,sort第二个参数必须返回一个Bool值,因为闭包只包含一个单一表达式a<b,并且表达式返回Bool类型,所以return可以省略

4)参数名称缩写

Swift 会自动为内联函数提供了参数名称缩写功能,您可以直接通过 $0,$1,$2 来顺序调用闭包的参数。

如果您在闭包表达式中使用参数名称缩写,您可以在闭包参数列表中省略对其的定义,并且对应参数名称缩写的类型会通过函数类型进行推断。 in 关键字也同样可以被省略,因为此时闭包表达式完全由闭包函数体构成,上面的例子可以简化成这样

sort(counts,
{$0<$1})   //$0
和 $1
表示闭包中第一个和第二个Int类型的参数。

看!Swift的闭包多洋气啊,竟然可以简化成这样

5)运算符函数

实际上还有一种更简单的方法,Swift中<符号可以作为一个函数来使用

sort(counts,
<)

2. Trailing 闭包

如果您需要将一个很长的闭包表达式作为最后一个参数传递给函数,可以使用 trailing 闭包来增强函数的可读性。 Trailing 闭包是一个书写在函数括号之外(之后)的闭包表达式,函数支持将其作为最后一个参数调用。上面的例子用Trailing 闭包形式表达如下

sort(counts){$0<$1}
  //$0
和 $1
表示闭包中第一个和第二个Int类型的参数。

注意:如果函数只需要闭包表达式一个参数,当您使用 trailing 闭包时,您甚至可以把 () 省略掉。

3. 捕获 (Caputure)

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

func makeIncrementor(forIncrement amount: Int) -> () -> Int {
    var runningTotal = 0
    func incrementor() -> Int {
        runningTotal += amount
        return runningTotal
    }
    return incrementor
}

注意:

Swift 会决定捕获引用还是拷贝值。 您不需要标注 amount 或者 runningTotal 来声明在嵌入的 incrementor 函数中的使用方式。 Swift 同时也处理 runingTotal 变量的内存管理操作,如果不再被 incrementor 函数使用,则会被清除。

          2) 闭包是引用类型

函数和闭包都是引用类型。闭包的赋值都是指针赋值。这意味着如果您将闭包赋值给了两个不同的常量/变量,两个值都会指向同一个闭包:

func makeIncrementor (forIncrement amount: Int) -> () -> Int {
    var runningTotal = 0
    func incrementor() -> Int {
        runningTotal += amount
        return runningTotal
    }
    return incrementor
}
let incrementByTen = makeIncrementor(forIncrement: 10)
let a = incrementByTen

这里a和incrementByTen都是指针,都他们中一个的值改变,另一个会随着一起改变

Swift学习笔记七:闭包

时间: 2024-10-20 22:19:11

Swift学习笔记七:闭包的相关文章

swift学习笔记(七)自动引用计数

与Object-c一样,swift使用自动引用计数来跟踪并管理应用使用的内存.当实例不再被使用时,及retainCount=0时,会自动释放是理所占用的内存空间. 注:引用计数仅适用于类的实例,因为struct和enumeration属于值类型,也就不牵涉引用,所以其存储和管理方式并不是引用计数. 当一个实例被初始化时,系统会自动分配一定的内存空间,用于管理属性和方法.当实例对象不再被使用时,其内存空间被收回. swift中的引用类型分为三种,即Strong强引用,weak弱引用和无主引用unw

Swift学习笔记之闭包

简介 (真的很简) 闭包的完整形态是这个样子的: { (parameters) -> returnType in statements } 写在一行里就是这样: {(parameters) -> (returnType) in statements} 形式 闭包以三种形式存在: 1.全局的函数都是闭包,它们有自己的名字,但是没有捕获任何值. 2.内嵌的函数都是闭包,它们有自己的名字,而且从包含他们的函数里捕获值. 3.闭包表达式都是闭包,它们没有自己的名字,通过轻量级的语法定义并且可以从上下文

【Swift】学习笔记(七)——闭包

1.什么是闭包 闭包简单的来说就是匿名函数.lambdas函数 ,书面点的来说就是闭包是自包含的函数代码块,可以在代码中被传递和使用,可以捕获和存储其所在上下文中任意常量和变量的引用. 这就是所谓的闭合并包裹着这些常量和变量,俗称闭包. 2.闭包采取的形式 前面在函数文章中,都定义的是全局函数,以及内嵌函数 实际上都是闭包的一种特殊形式. 全局函数是一个有名字但不会捕获任何值的闭包 嵌套函数是一个有名字并可以捕获其封闭函数域内值的闭包 闭包表达式是一个利用轻量级语法所写的可以捕获其上下文中变量或

Swift学习笔记七:集合

数组 Array 数组的创建 OC 中使用 @[] 定义数组, Swift 中使用 [] 定义数组 [类型] 表示数组中存放的都是该类型的元素 Swift 中数组中的元素可以是基本数据类型 // 创建数组 var array1: Array<Int> vararray2:Array<Int> = [2,3] var array3: [Int] var array33 = [Int]() array1 = Array(arrayLiteral: 1, 2, 3, 4) var arr

Swift学习笔记七

控制流 Swift提供了和C类似的控制流表达式,包括for.while.if.switch.当然也包括break和continue这种语句来引导控制流到某个指定点的语句. 在C的for基础上,Swift提供了更强大的for-in,遍历起来更方便. Swift的switch也比C中的更强大,其中的case在执行之后并不会继续执行下一个case,这样就避免了C中忘记写break时产生的逻辑错误.同时,case也能匹配更多的模式,包括间隔匹配,元组等,被匹配的值可以被赋值给变量或者常量,以便在case

swift学习笔记(七)自己主动引用计数

与Object-c一样,swift使用自己主动引用计数来跟踪并管理应用使用的内存.当实例不再被使用时,及retainCount=0时,会自己主动释放是理所占用的内存空间. 注:引用计数仅适用于类的实例,由于struct和enumeration属于值类型,也就不牵涉引用,所以其存储和管理方式并非引用计数. 当一个实例被初始化时,系统会自己主动分配一定的内存空间,用于管理属性和方法.当实例对象不再被使用时,其内存空间被收回. swift中的引用类型分为三种,即Strong强引用,weak弱引用和无主

swift学习笔记(六)析构过程和使用闭包对属性进行默认值赋值

一.通过闭包和函数实现属性的默认值 当某个存储属性的默认值需要定制时,可以通过闭包或全局函数来为其提供定制的默认值. 注:全局函数结构体和枚举使用关键字static标注    函数则使用class关键字标注 当对一个属性使用闭包函数进行赋值时,每当此属性所述的类型被创建实例时,对应的闭包或函数会被调用,而他们的返回值会被作为属性的默认值. ESC: Class SomeCLass{ let someProperty:SomeType={ //给someProperty赋一个默认值 //返回一个与

swift学习笔记(三)关于拷贝和引用

在swift提供的基本数据类型中,包括Int ,Float,Double,String,Enumeration,Structure,Dictionary都属于值拷贝类型. 闭包和函数同属引用类型 捕获则为拷贝.捕获即定义这些常量和变量的原作用域已不存在,闭包仍然可以在闭包函数体内引用和修改这些值 class属于引用类型. Array的情况稍微复杂一些,下面主要对集合类型进行分析: 一.关于Dictionary:无论何时将一个字典实例赋给一个常量,或者传递给一个函数方法时,在赋值或调用发生时,都会

Lua学习笔记(七):迭代器与泛型for

1.迭代器与闭包 迭代器是一种支持指针类型的结构,它可以遍历集合的每一个元素.在Lua中我们常常使用函数来描述迭代器,每次调用该函数就返回集合的下一个元素. 迭代器需要保留上一次成功调用的状态和下一次成功调用的状态,也就是他知道来自于哪里和将要前往哪里.闭包提供的机制可以很容易实现这个任务.记住:闭包是一个内部函数,它可以访问一个或者多个外部函数的外部局部变量.每次闭包的成功调用后这些外部局部变量都保存他们的值(状态).当然如果要创建一个闭包必须要创建其外部局部变量.所以一个典型的闭包的结构包含