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

这篇具有很好参考价值的文章主要介绍了关于Swift中闭包和OC中block对局部变量基本数据类型值的捕获。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

翻了很多文章,发现关于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,也好理解。
看答案:
关于Swift中闭包和OC中block对局部变量基本数据类型值的捕获,swift,iOS,swift,开发语言,ios
闭包内输出是1 ,这好像和OC中block是不一样的?接着往下看。

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

关于Swift中闭包和OC中block对局部变量基本数据类型值的捕获,swift,iOS,swift,开发语言,ios

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

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

输出结果是什么呢?
第一个输出是1,很好理解。
第二个输出是闭包里的i,是1,刚才已经看到了。
第三个输出输出多少呢?
看答案:
关于Swift中闭包和OC中block对局部变量基本数据类型值的捕获,swift,iOS,swift,开发语言,ios
答案是2。说明闭包内修改的值,也会反应到闭包外部。

GPT给的答案也是错误的:
关于Swift中闭包和OC中block对局部变量基本数据类型值的捕获,swift,iOS,swift,开发语言,ios

再看一个例子:

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

输出会是什么呢?
关于Swift中闭包和OC中block对局部变量基本数据类型值的捕获,swift,iOS,swift,开发语言,ios
所以这几个例子都证明了,闭包对变量进行捕获,是将变量复制到了堆上,之后不论是闭包内,还是闭包外,操作的值,都是堆上的这个值,闭包对这个值强持有。

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

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

四:捕获列表

那么怎么做到,在定义时就确定捕获的值呢?就像block那样,没有__block修饰符的int?
使用捕获列表 [] in
关于Swift中闭包和OC中block对局部变量基本数据类型值的捕获,swift,iOS,swift,开发语言,ios
很容易理解,不再赘述。文章来源地址https://www.toymoban.com/news/detail-602381.html

到了这里,关于关于Swift中闭包和OC中block对局部变量基本数据类型值的捕获的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Swift与OC的混编

    在一位前辈的博客里看到了关于iOS开发的各种语言的混编,浅浅学习一下怎么使用。不得不说语言混编的开发者是真的🐮🍺 新建一个Swift文件 创建一个OC的类 选择language为OC 继续往下走,会跳出这个界面,直接选择蓝色这个就可以 然后项目里会出现这个文件 引入我们新建的

    2024年02月15日
    浏览(30)
  • OC与Swift的相互调用

    1、在 Build Settings 搜索 Packaging ,设置 Defines Module 为 YES  2、新建 LottieBridge.swift 文件,自动生成桥 ProductName-Bridging-Header.h  3、在 LottieBridge.swift 中,定义Swift类继承于OC类,声明 @objcMembers 或 @objc ,实现相关方法 4、在OC代码中引用 ProductName-Swift.h ,调用Swift相关方法 1、在 Pr

    2024年02月14日
    浏览(34)
  • OC调用Swift编写的framework

    随着swift趋向稳定,越来越多的公司都开始用swift来编写苹果相关的业务了,关于swift的利弊这里就不多说了。这里详细介绍OC调用swift编写的framework库的步骤 1、新建项目,选择framework 2、填写framework的名称、组织ID、语言选择swift  3、新建一个test.swift文件,编写测试代码 4、编

    2024年02月12日
    浏览(38)
  • swift 闭包本质,闭包表达式,尾随闭包

    一个函数和它所捕获的变量/常量环境组合起来,称为闭包 一般指定义在函数内部的函数 一般它所捕获的是外层函数的局部变量/常量 结果: 解释: 闭包能够使用其外层函数的局部变量,所以函数值能够增加 本质: 编译器给sum函数外层getFn函数的count属性分配了堆空间,所以

    2024年01月20日
    浏览(25)
  • OC和Swift混编,导入头文件‘xxx-Swift.h‘ file not found

    在OC的项目里加入Swift代码,创建完桥接文件后,需要倒入Swift头文件,头文件的格式为“项目名-Swift.h”。 如下图,我在Xcode上看到我的项目名为YichangPark,导入 #import \\\"YiChangPark-Swift.h\\\" 之后提示 “YiChangPark-Swift.h”file not found. 言外之意,就是没有找到头文件! 解决办法: 1

    2024年02月10日
    浏览(31)
  • OC和Swift混合开发(Pod私有库的相互引用)

    环境 Xcode 12.4,    Swift:5.0 概述:该文档主要介绍OC和Swift混合开发相互调用,包括3大类情况和12种具体情形。 1. 主工程内的混合互调, 2. 主工程和Pod三方库之间的混合互调, 3. Pod三方库和其他Pod三方库之间的混合互调。 1. 主工程内的OC 调用 主工程内的OC: #import \\\"NSObject.

    2024年03月09日
    浏览(26)
  • iOS开发Swift-闭包

    将很长的闭包表达式作为最后一个参数传递给函数,不用写出他的参数标签。 嵌套函数可捕获其外部函数所有参数、变量、常量。 当一个闭包作为一个参数传到一个函数中,但闭包在函数返回之后才被执行,则称闭包逃逸。 标注@escaping,表示允许闭包逃逸。  包装传递给函数

    2024年02月11日
    浏览(39)
  • swift 闭包捕获列表

    因为  clousre  已经申明将  car  复制进去了 ([car]) ,此时 clousre  里的  car  是个局部变量,不再与外面的  car 有关,所以会打印出”I drive Benz”。 此时面试官微微一笑,将题目略作修改如下: 此时 closure 没有申明复制拷贝 car ,所以 clousre 用的还是全局的 car 变量,此

    2024年03月09日
    浏览(26)
  • IOS-闭包学习-Swift

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

    2024年01月24日
    浏览(36)
  • (flutter)黑苹果系统 Xcode iOS flutter 跑通真机模拟器 此oc clover 彼oc swift

    前段时间写了关于flutter的一系列基础知识和入门的一些坑,中间把ios端的项目编译部署等工作一带而过,这里我觉得还是有必要专门写一篇文章来讲讲这个,顺便把环境问题也一起说了。 我们都知道开发ios应用需要用到苹果电脑,即使flutter也不例外,flutter编译构建需要Xc

    2024年02月07日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包