笔记摘要(七)--Swift3.0之闭包

  • 闭包是自包含的代码块,可以在代码中被传递和使用。与C、OC中的block相似。

  • 闭包可以捕获和存储其所在上下文中任意常量和变量的引用。

  • 闭包采取如下三种形式之一:

    • 全局函数是一个有名字但不会捕获任何值的闭包
    • 嵌套函数是一个有名字并可以捕获其封闭函数域内值的闭包
    • 闭包表达式是一个利用轻量级语法所写的可以捕获其上下文中变量或常量值的匿名闭包
  • 闭包表达式

    • 闭包的函数体部分由关键字in引入。该关键字表示闭包的参数和返回值类型定义已经完成,闭包函数体即将开始

    • 单行表达式闭包可以通过省略return关键字来隐式返回单行表达式的结果

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

      let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
      func backward(_ s1: String, _ s2: String) -> Bool{   
         return s1 > s2
      }
      var reversedNames = names.sorted(by: backward)
      reversedNames = names.sorted(by: {(s1: String, s2: String) -> Bool in 
        return s1 > s2
      })
      //根据上下文推断类型
      reversedNames = names.sorted(by: {s1, s2 in return s1 > s2})
      //单表达式闭包隐式返回
      reversedNames = names.sorted(by: {s1, s2 in s1 > s2})
      //参数名称缩写
      reversedNames = names.sorted(by: {$0 > $1})
      //运算符方法
      reversedNames = names.sorted(by: >)
      
  • 尾随闭包

    • 如果你需要将一个很长的闭包表达式作为最后一个参数传递给函数,可以使用尾随闭包来增强函数的可读性。
    • 格式:
      func someFunctionThatTakesAClosure(closure: () -> Void){
      //函数体部分
      }
      //以下是不使用尾随闭包进行函数调用
      someFunctionThatTakesAClosure {
      //闭包主体部分
      }
      //以下是使用尾随闭包进行函数调用
      someFunctionThatTakesAClosure(){
      //闭包主体部分
      }
  • 值捕获

    • 可以捕获值的闭包的最简单形式是嵌套函数。
    • 为了优化,如果一个值不会被闭包改变,或者在闭包创建后不会改变,swift可能会改为捕获并保存一份对值的拷贝;swift也会负责被捕获变量的所有内存管理工作,包括释放不再需要的变量。
    • 如果你将闭包赋值给一个类实例的属性,并且该闭包通过访问该实例或者成员而捕获了该实例,你将在闭包和该实例间创建一个循环强引用。swift使用捕获列表来打破这种循环强引用。
  • 闭包是引用类型

    • 函数和闭包都是引用类型。无论你将函数或闭包赋值给一个常量还是变量,你实际上都是将常量或变量的值设置为对应函数或闭包的引用。
  • 逃逸闭包

    • 当一个闭包作为参数传到一个函数中,但是这个闭包在函数返回之后才被执行,我们称该闭包从函数中逃逸。
    • 定义接受闭包作为参数的函数时,可以在参数名之前标注@escaping,用来指明这个闭包是允许“逃逸”出这个函数的。
    • 标记为逃逸闭包,就需要在闭包中显式的引用self。
      var completionHandlers: [() -> Void] = []
      func someFunctionWithEscapingClosure(completionHandler: @escaping () -> Void){
      completionHandlers.append(completionHandler)
      }
      func someFunctionWithNoneEscapingClosure(closure: () -> Void){
      closure()
      }
      class SomeClass{
      var x = 10
      func doSomething() {
      someFunctionWithEscapingClosure {
      self.x = 100
      }
      someFunctionWithNoneEscapingClosure {
      x = 200 } }}
      let instance = SomeClass()
      instance.doSomething()
      print(instance.x)completionHandlers.first?()
      打印:200
      print(instance.x)
      打印:100
  • 自动闭包

    • 自动创建的闭包;用于包装传递给函数作为参数的表达式;

    • 不接受任何参数,被调用时,会返回被包装在其中的表达式的值;这种便利语法可以省略花括号,用一个普通的表达式来代替显式的闭包。

      //闭包如何延时求值
      var customersInLine = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
      print(customersInLine.count)
      //打印出 "5"
      let customerProvider = {customersInLine.remove(at: 0)}
      print(customersInLine.count)
      //打印出 "5"
      print("now serving \(customerProvider())!")
      //打印出 "now serving Chris!"
      print(customersInLine.count)
      //打印出“4”
      

    func serve(customer customerProvider: () -> String){  
      print("now serving \(customerProvider())!")
    }
    serve(customer: {customersInLine.remove(at: 0)})
    //自动闭包
    func serve(customer customerProvider: @autoclosure () -> String){   
      print("now serving \(customerProvider())!")}
    serve(customer: customersInLine.remove(at: 0))

    注意:过度使用auto closures会让代码变得难以理解。上下文和函数名应该能够清晰的表明求值是被延时执行的
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,657评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,662评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,143评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,732评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,837评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,036评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,126评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,868评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,315评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,641评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,773评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,470评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,126评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,859评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,095评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,584评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,676评论 2 351

推荐阅读更多精彩内容

  • 86.复合 Cases 共享相同代码块的多个switch 分支 分支可以合并, 写在分支后用逗号分开。如果任何模式...
    无沣阅读 1,354评论 1 5
  • 以下翻译自Apple官方文档,结合自己的理解记录下来。翻译基于 swift 3.0.1 原文地址 Closure...
    艺术农阅读 1,524评论 0 3
  • #闭包(Closures) 本页包含内容: - 闭包表达式(Closure Expressions) - 尾随闭包...
    刺骨寒阅读 1,250评论 0 0
  • 闭包是功能性自包含模块,可以在代码中被传递和使用。Swift中的闭包与 C 和 Objective-C中的 blo...
    AirZilong阅读 348评论 0 2
  • 1. 查看安装的所有JDK 版本和路径 1> 查看安装的所有JDK 版本和路径以及当前使用的是哪一个JDK 最后一...
    小芸论阅读 357评论 0 0