本文介绍: 翻了很多文章发现关于Swift闭包关于上下文变量捕获这块,都没有说的很详细,或者Swift2这样的老版本已经不适用了,问了GPT也是和自己实验结果不一样,记录下来。

翻了很多文章发现关于Swift闭包关于上下文变量捕获这块,都没有说的很详细,或者Swift2这样的老版本已经不适用了,问了GPT也是和自己实验的结果不一样,记录下来。

一:OC的block

首先,回顾一下OC中的block
block局部变量基本数据类型捕获,是在创建捕获了值,并保存副本自己结构体中,修改也是修改副本,不会影响到原本的值。
例子

typedef void (^MyBlock)(void);

- (MyBlock)createBlock {
    int number = 10;
    MyBlock block = ^{
        NSLog(@"Captured value: %d", number);
    };
    number = 20;
    return block;
}

- (void)executeBlock {
    MyBlock myBlock = [self createBlock];
    myBlock(); 
}

最后输出是:

Captured value: 10

二:__block修饰符

如果希望block内部修改的值是原本的值,或者希望block捕获的值后面还会变化,需要对原本的变量添加__block修饰符

typedef void (^MyBlock)(void);

- (MyBlock)createBlock {
    __block int number = 10;
    MyBlock block = ^{
        NSLog(@"Captured value: %d", number);
    };
    number = 20;
    return block;
}

- (void)executeBlock {
    MyBlock myBlock = [self createBlock];
    myBlock(); 
}

最后输出是:

Captured value: 20

三:Swift闭包

那Swift闭包对局部基本数据类型变量捕获怎样的呢?Swift没有__block修饰符,是不是就没法做到block那样的功能了呢?
答案是否定的,例子

var i = 0
let closure = {
	print("(i)")
}
i += 1
print("(i)")
closure()
print("(i)")

输出结果是什么呢?
第一个输出是1,很好理解
第二个输出是闭包里的i,输出多少呢?
第三个输出是1,也好理解
答案
在这里插入图片描述
闭包内输出是1 ,这好像和OC中block是不一样的?接着往下看。

顺便,很无奈的是,GPT给的答案也是错误的:

在这里插入图片描述

那么,看上去和OC中捕获__block修饰符int是一样的?继续尝试

var i = 0
let closure = {
    print("(i)")
    i += 1
}
i += 1
print("(i)")
closure()
print("(i)")

输出结果是什么呢?
一个输出是1,很好理解
第二个输出是闭包里的i,是1,刚才已经看到了。
第三个输出输出多少呢?
看答案:
在这里插入图片描述
答案是2。说明闭包内修改的值,也会反应到闭包外部

GPT给的答案也是错误的:
在这里插入图片描述

再看一个例子

var i = 0
let closure = {
    print("(i)")
}
i += 1
closure()
i += 1
closure()
i += 1
closure()

输出会是什么呢?
在这里插入图片描述
所以这几个例子都证明了,闭包对变量进行捕获,是将变量复制到了堆上,之后不论是闭包内,还是闭包外,操作的值,都是堆上的这个值,闭包对这个值强持有。

捕获值的本质是将变量存储到堆上。

1、一个闭包能够从上下文捕获已经定义常量变量,并且能够在其函数体内引用修改这些值,即使这些定义常量变量的原作用域存在
2、修改捕获值实际是修改堆区中的value值;
3、当每次重新执行当前函数时,都会重新创建内存空间

四:捕获列表

那么怎么做到,在定义时就确定捕获的值呢?就像block那样,没有__block修饰符int
使用捕获列表 [] in
在这里插入图片描述
很容易理解,不再赘述。

原文地址:https://blog.csdn.net/z040145/article/details/131849311

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_31466.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注