重学Swift第七篇:闭包

前言

本节内容需要分析IR代码,语法可参考LLVM语言参考手册

一、闭包是什么

闭包是可以在代码中被传递和引用的功能性独立代码块。闭包可以捕获和存储其所在上下文中任意常量和变量的引用,这就是所谓的闭合并包裹那些常量和变量,因此被称为“闭包”。 作为一种优化,如果一个值没有改变或者在闭包的外面,Swift 可能会使用这个值的拷贝而不是捕获。Swift 会为你管理在捕获过程中涉及到的所有内存操作。
闭包采用如下三种形式之一:

  • 全局函数一个有名字不会捕获任何值的闭包 (对标NSGlobalBlock?)

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

  • 闭包表达式是一个利用轻量级语法所写的可以捕获其上下文中变量或常量值匿名闭包。

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

    { (parameters) -> return type in
    	 statements
    }
    

    下面以sorted()方法为例来对一般语法进行简化

    //一般写法
    sorted(by: {
          (s1: String, s2: String) -> Bool in
    	return s1 > s2
    })
    //从语境中推断类型
    sorted(by: {
          s1, s2 in return s1 > s2 } )
    //从单表达式闭包隐式返回
    sorted(by: {
          s1, s2 in s1 > s2 } )
    //简写的实际参数名
    sorted(by: {
          $0 > $1 } )
    //运算符函数
    sorted(by: >)
    //尾随闭包
    sorted() {
          $0 > $1 }
    sorted {
          $0 > $1 }
    

闭包是引用类型,可传递给函数做参数。

  • 逃逸闭包:当闭包作为一个实际参数传递给一个函数的时候,我们就说这个闭包逃逸了,因为它是在函数返回之后调用的。用@escaping在形式参数前修饰。主要场景为延时调用,如接口回调、GCD延时。
  • 自动闭包:一种自动创建的用来把作为实际参数传递给函数的表达式打包的闭包。它不接受任何实际参数,并且当它被调用时,它会返回内部打包的表达式的值。这个语法的好处在于通过写普通表达式代替显式闭包而使你省略包围函数形式参数的括号。用@autoclosure在形式参数前修饰。滥用自动闭包会导致你的代码难以读懂。上下文和函数名应该写清楚求值是延迟的。

二、IR分析

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

var makeInc = makeIncrementer(forIncrement: 10)
var value = makeInc()

以官方的这个代码为例,通过swiftc -emit-ir main.swift > main.ll转为IR代码,下面选取一部分代码进行解释

  • 数据结构定义
%swift.function = type {
    i8*, %swift.refcounted* }
%swift.full_boxmetadata = type {
    void (%swift.refcounted*)*, i8**, %swift.type, i32, i8* }
%swift.refcounted = type {
    %swift.type*, i64 }
%swift.type = type {
    i64 }
%TSi = type <{
    i64 }>
  • 全局变量
@"symbolic Si" = linkonce_odr hidden constant <{
    [2 x i8], i8 }> <{
    [2 x i8] c"Si", i8 0 }>, section "__TEXT,__swift5_typeref, regular, no_dead_strip", align 2
@"\01l__swift5_reflection_descriptor" = private constant {
    i32, i32, i32, i32 } {
    i32 1, i32 0, i32 0, i32 trunc (i64 sub 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值