关于Swift中闭包和OC中block对局部变量基本数据类型值的捕获

news2024/10/7 20:25:17

翻了很多文章,发现关于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
在这里插入图片描述
很容易理解,不再赘述。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/782521.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

varnish入门

b站视频 官网 docker安装varnish 某位博客园的varnish系列 varnish04-varnish如何使用VCL 3varnish的原理 varnish是什么 varnish的安装 VCL基础 Varnish Configuration Language (VCL)是一种特定于领域的语言,可以用于描述Varnish Cache服务如何处理请求和缓存…

ONE-PEACE论文解读

文章目录 1. 摘要2. 引言3. 算法3.1 结构模态自适应器3.2 模态融合编码器3.3 任务 4. 实验4.1 视觉任务4.2 音频任务4.3 视觉语言任务4.4 消融实验4.5 zero-shot检索 5. 结论 论文: 《ONE-PEACE: EXPLORING ONE GENERAL REPRESENTATION MODEL TOWARD UNLIMITED MOD…

Mysql最左匹配原则和索引下堆

前言: 最左匹配的基础是联合索引 联合索引 联合索引也称为符合索引,适用于多条件查询。 简单说,它是按多个列建立起来的索引,此外联合索引也是有顺序的。 如下图,以A列和B列建立复合索引,某一层节点&…

学习路之PHP--计算2个坐标点之间距离、时间比较

一、计算2个坐标点之间距离 /** * 根据起点坐标和终点坐标测距离 * param [array] $from [起点坐标(经纬度),例如:array(118.012951,36.810024)] * param [array] $to [终点坐标(经纬度)] * param [bool] $km 是否以公里为单位 false:米 true:公里(千米) …

matlab pcnormals()函数的功能 详解

官方解释: pcnormals - Estimate normals for point cloud This MATLAB function returns a matrix that stores a normal for each point in the input ptCloud. normals pcnormals(ptCloud) normals pcnormals(ptCloud,k) 输入参数 ptClo…

捷米特PROFINET总线协议网关介绍

关于PROFINET PROFINET由PROFIBUS国际组织(PROFIBUS International,PI)推出,是新一代基于工业以太网技术的自动化总线标准。 PROFINET为自动化通信领域提供了一个完整的网络解决方案,囊括了诸如实时以太网、运动控制…

详解 Linux 常用命令

目录 简单介绍 Linux 左侧信息栏 命令 ls ll cd pwd ctrl l touch cat man echo vim vimtutor mkdir rm cp mv grep ps 面试题: 简单介绍 当我们说"Linux"时,通常指的是一种开源的计算机操作系统。Linux 是一个基于 UNIX 操作系…

24.实现线性拟合和相关系数(matlab程序)

1.简述 1. 基本语法 1.1 corr函数基本语法 语法 说明 rho corr(X) 返回输入矩阵X中每对列之间的两两线性相关系数矩阵。 rho corr(X, Y) 返回输入矩阵X和Y中每对列之间的两两相关系数矩阵。 [rho, pval] corr(X, Y) 返回pval,一个p值矩阵&#xff0c…

SpringBoot静态资源访问及参数处理

静态资源访问: 资源访问: 1:Spring Boot 支持静态和模板化的欢迎页面。它首先在配置的静态内容位置中查找index.html文件。如果未找到,则查找index相关模板。如果找到任一,它将自动用作应用程序的欢迎页面。 2&…

【单片机】MSP430F149单片机,晨启,音乐播放器,蜂鸣器音乐

四、音乐播放器 任务要求: 设计制作一个简易音乐播放器(通过手柄板上的蜂鸣器发声,播放2到4首音 乐),同时LED模块闪烁,给人视、听觉美的感受。 评分细则: 按下播放按键P15开始播放音乐&#x…

MCP4725介绍和STM32模拟IC2驱动

一.MCP4725 简单总结为下面几个特点。 1路DAC输出 12位分辨率 I2C 接口(标准,快速,高速支持) 供电电压2.7-5.5 内部EEPROM存储设置 I2C地址可配置(A0)(A1、A2内置,默认为‘00’&…

『Dubbo SPI源码分析』@Adaptive 机制分析

『Dubbo SPI源码分析』Adaptive 机制分析 基于 2.7.0 版本上一章:『Dubbo SPI源码分析』依赖注入机制分析 创建测试 demo 首先创建一个接口,举例为 Car package com.luban.dubbo_spi.api;SPI public interface Car {public void getColor();Adaptive…

pycharm中运行py文件时,报错:找不到自己编写的包等目录问题ModuleNotFoundError: No module named ‘xxx‘

【问题描述】:pycharm中运行py文件时,报错:找不到自己编写的包等目录问题 【报错】: ModuleNotFoundError: No module named ‘xxx’ ERROR: file not found 【问题定位】:运行的py文件和用到的包或者数据不在同一个文件目录下时…

【HanLP】--自然语言处理场景应用

目录 一、前言二、Springboot集成HanLP三、HanLP分词四、HanLP的关键字提取一、前言 HanLP 是由一系列模型与算法组成的工具包,主要功能包括分词、词性标注、关键词提取、自动摘要、依存句法分析、命名实体识别、短语提取、拼音转换、简繁转换等等。 下面将介绍HanLP如何本地…

PHP swoole从入门到精通(一、如何安装swoole及phpStorm服务端代码同步设置)

swoole安装直接在宝塔后台-》安装扩展 phpStorm服务端代码同步设置 https://www.cnblogs.com/yszr/p/9009961.html 软件下载地址 代码上传下载,鼠标右击任何一个文件或者文件夹,选择 Development->上传/下载/同步 点击工具栏Tools->Development…

前端个人年终工作总结精选7篇

一、工作总结的种类 1、按总结的时间分,有年度总结、半年总结、季度总结、学期总结。进行某项重大任务时,还要分期总结或叫阶段总结。 2、按总结的范围分,有单位总结、个人总结、综合性总结、专题总结等。 3、按总结的性质分,有…

科普 | OSI模型

本文简要地介绍 OSI 模型 1’ 2’ 3。 更新:2023 / 7 / 23 科普 | OSI模型 术语节点链路协议网络拓扑 概念作用结构应用层表示层会话层传输层网络层数据链路层物理层 数据如何流动OSI 和TCP/IP 的对应关系和协议参考链接 术语 节点 节点( Node &#…

vue基本语法(个人学习笔记一)

目录 友情提醒第一章、vue概述1.1)vuej介绍1.2)Vue 周边库1.3)MVVM的思想 第二章、借助CDN使用Vue2.1)vue简单引入:引入js文件2.2)简单的Vue程序 第三章、vue的基本语法3.1)Vue的数据绑定&#…

在工作中如何对文件进行批量标记和编号

大家在日常工作中,是如何给文件该或文件夹批量重命名或添加编号,有没有怎么好的方法,可以一键批量操作。 经过小编多次操作经验,得到一个结论,可以通过《文件批量改名高手》对这些文件进行批量标记和编号,…

WebGL 概念和基础入门

WebGL 概念和基础入门 WebGL 是什么 对于 WebGL 百度百科给出的解释是 WebGL 是一种 3D 绘图协议,而对此维基百科给出的解释却是一种 JavaScript API。由于 WebGL 技术旨在帮助我们在不使用插件的情况下在任何兼容的网页浏览器中开发交互式 2D 和 3D 网页效果&…