Swift   发布时间:2022-03-31  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了Swift3.0 闭包(blcok)的全面介绍及使用大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

概述

闭包是自包含的函数代码块,可以在代码中被传递和使用。Swift 中的闭包与 C 和 Objective-C 中的代码块(blocks)以及其他一些编程语言中的匿名函数比较相似。闭包可以捕获和存储其所在上下文中任意常量和变量的引用。被称为包裹常量和变量。 Swift 会为你管理在捕获过程中涉及到的所有内存操作。 闭包表达式语法有如下的一般形式: { (parameters) -> retur

闭包是自包含的@L_674_0@@L_772_1@块,可以在@L_772_1@中被传递和使用。Swift 中的闭包与 C 和 Objective-C 中的@L_772_1@块(blocks)以及其他一些编程语言中的匿名@L_674_0@比较相似。闭包可以捕获和存储其所在上下文中任意常量和变量的引用。被称为包裹常量和变量。 Swift 会为你管理在捕获过程中涉及到的所有内存操作。

闭包表达式语法有如下的一般形式:

{
    (parameters) -> returnType in
      statements
 }
  • 这里的参数(parameters),可以是in-out(输入输出参数),但不能设定认值。如果是可变参数,必须放在最后一位,不然编译器报错。元组也可以作为参数或者返回值。
  • 闭包的@L_674_0@体部分由关键字in引入。该关键字表示闭包的参数和返回值类型定义已经完成,闭包@L_674_0@体即将开始

例如:

let  sum:(Int,int) -> Int = {(a : Int,b : int) -> Int in
          return a + b  
}
 print(sum(3,4))

由于可以推断出闭包的参数和返回值类型,所以闭包表达式可以表达为:

let  sum:( Int,Int ) -> Int = { a,b  in
          return a + b 
 }

单表达式闭包隐式返回

单行表达式闭包可以通过省略 return 关键字来隐式返回单行表达式的结果,如上版本的例子可以改写为:

let  sum:( Int,b  in
          a + b 
 }

有参数没有返回值的写法

let say0:(String) ->Void = {
    (name: String) in
    print("hi \(Name)")
}
say0("cdh")
//输出结果:  hi cdh

没有参数没有返回值写法

let say1:() ->Void = {
    () -> () in // 当没有参数也没有返回值是这行都可以省略
    print("hi cdh")
}
say1()
//输出结果:  hi cdh

闭包的声明

Swift用typealias声明闭包数据类型,类似于Objective-C中的typedef

typealias  TESTBlcok = (Int,int) -> Int

let test : TESTBlcok = {( a,b ) in  a + b}

let result = test( 12,20 )

计算结果是 32

尾随闭包

若将闭包作为@L_674_0@最后一个参数,可以省略参数标签,然后将闭包表达式写在@L_674_0@调用括号后面

func testFunction(TESTBlock: ()->Void){
    //这里需要传进来的闭包类型是无参数和无返回值的
    TESTBlock()
}
//正常写法
testFunction(TESTBlock: {
    print("正常写法")
})
//尾随闭包写法
testFunction(){
    print("尾随闭包写法")
}
//也可以把括号去掉,也是尾随闭包写法。推荐写法
testFunction { 
    print("去掉括号的尾随闭包写法")
}

值捕获

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

Swift 中,可以捕获值的闭包的最简单形式是嵌套@L_674_0@,也就是定义在其他@L_674_0@的@L_674_0@体内的@L_674_0@。嵌套@L_674_0@可以捕获其外部@L_674_0@所有的参数以及定义的常量和变量。”

例如:

func makeIncrementer(forIncrement amount: int) -> () -> Int {
    var running@R_283_10586@l = 0
    func incrementer() -> Int {
        running@R_283_10586@l += amount
        return running@R_283_10586@l
    }
    return incrementer
}
@H_989_14@makeIncrementor 返回类型为 () -> Int。这意味着其返回的是一个@L_674_0@,而非一个简单类型的值。该@L_674_0@在每次调用时不接受参数,只返回一个 Int 类型的值。

@H_989_14@makeIncrementer(forIncrement:) @L_674_0@定义了一个初始值为 0 的整型变量 running@R_283_10586@l,用来存储当前总计数值。该值为 incrementor 的返回值。

@H_989_14@makeIncrementer(forIncrement:) 有一个 Int 类型的参数,其外部参数名为 forIncrement,内部参数名为 amount,该参数表示每次 incrementor 被调用时 running@R_283_10586@l 将要增加的量。makeIncrementer @L_674_0@还定义了一个嵌套@L_674_0@ incrementor,用来执行实际的增加操作。该@L_674_0@简单地使 running@R_283_10586@l 增加 amount,并将其返回。

如果我们单独虑嵌套@L_674_0@ incrementer(),会发现它有些不同寻常:

func incrementer() -> Int {
    running@R_283_10586@l += amount
    return running@R_283_10586@l
}

incrementer() @L_674_0@并没有任何参数,但是在@L_674_0@体内访问了 running@R_283_10586@l 和 amount 变量。这是因为它从外围@L_674_0@捕获了 running@R_283_10586@l 和 amount 变量的引用。捕获引用保证了 running@R_283_10586@l 和 amount 变量在调用完 makeIncrementer 后不会消失,并且保证了在下一次执行 incrementer @L_674_0@时,running@R_283_10586@l 依旧存在。

注意 :为了优化,如果一个值不会被闭包改变,或者在闭包创建后不会改变,Swift 可能会改为捕获并保存一份对值的拷贝。 Swift 也会负责被捕获变量的所有内存管理工作,包括释放不再需要的变量。

闭包引起的循环强引用

//定义一个全局变量:

        vara:Int=9

        varclosure: ()->Void= {

           /**

     认闭包会对它访问的对象执行强引用。
     这个地方访问了self,导致调用该闭包的时候引用计数+1
     如果闭包属性中没有直接或者间接访问self,就不会产生循环强引用。
             可以使用uNowned或者weak 来修饰self。
             当然两种存在区别。Swift中的weak、uNowned对应Objective-C中的weak、unsafe_unretained,
             这表明前者在对象释放后 会自动将对象置为nil,而后者依然保持一个“无效的”引用,如果此时调用这
             个“无效的”引用将会引起程序崩溃。对于后者的使用,我们必须保证访问的时候对象没有释放。
             相反,weak则友好一点我们也更加习惯使用它,

      */

     [weakself]in

       print("a=\(self.a)")

}

逃逸闭包

一个闭包作为参数传到一个@L_674_0@中,但是这个闭包在@L_674_0@返回之后才被执行,我们称该闭包从@L_674_0@中逃逸。当你定义接受闭包作为参数的@L_674_0@时,你可以在参数名之前标注 @escaping,用来指明这个闭包是允许“逃逸”出这个@L_674_0@的。

自动闭包

自动闭包是一种自动创建的闭包,用于包装传递给@L_674_0@作为参数的表达式。这种闭包不接受任何参数,当它被调用的时候,会返回被包装在其中的表达式的值。这种便利语法让你能够省略闭包的花括号,用一个普通的表达式来代替显式的闭包。

自动闭包让你能够延迟求值,因为直到你调用这个闭包,@L_772_1@段才会被执行。延迟求值对于那些有副作用(Side Effect)和高计算成本的@L_772_1@来说是很有益处的,因为它使得你能控制@L_772_1@的执行时机。

大佬总结

以上是大佬教程为你收集整理的Swift3.0 闭包(blcok)的全面介绍及使用全部内容,希望文章能够帮你解决Swift3.0 闭包(blcok)的全面介绍及使用所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。