swift函数参数指针传递inout和@escaping冲突的解决方法

article/2025/10/17 11:45:55

这里写目录标题

  • 需求
  • 解决方法
  • 容易产生的问题
  • 总结

今天深入解决关于函数参数指针的问题。问题是这样,我在swift的一个函数里面,参数里需要传递一个指针类型的Int,但是这个函数里面还有一个逃逸闭包@escaping,于是就会报错这样:Escaping closure captures ‘inout’ parameter ‘selectRow’ ,意思是说:逃逸闭包补货了一个inout参数 selectRow

需求

我每次调用下面的swift方法,都会弹出一个PickerView,并且,设置label的text,同时,记录上次选中的selectRow

 func setTimePicker2(selectRow:inout Int,label:UILabel){let vc = TDWPickerVC(items: timeItems, titleLabelStr: "请选择时间段",selectRow: selectRow) {print("点击取消")} confirmBlock: { (str,row) inprint("点击确定",str)selectRow = rowlabel.text = str}print("time1VSelectRow=",selectRow )vc.modalPresentationStyle = .customvc.modalTransitionStyle = .crossDissolvenavigationController?.present(vc, animated: true, completion: nil)}

下面是调用的代码

var time3VSelectRow = 0//类成员变量
setTimePicker2(selectRow: &time3VSelectRow, label: time3Label)//方法中的调用
``
再看控制器的定义里面有一个@escaping的逃逸闭包类型
```swiftinit(items:[String],titleLabelStr:String,selectRow:Int, cancleBlock:@escaping BlockVoid,confirmBlock:@escaping BlockStr) {self.titleLabelStr = titleLabelStrself.cancleBlock = cancleBlockself.confirmBlock = confirmBlockself.items = itemsself.selectRow = selectRowsuper.init(nibName: "TDWPickerVC", bundle: nil)}

错误原因就是编译器不允许逃逸闭包@escaping捕获inout类型参数,因为inout类型传入的是一个指针,参数可以在外面更改,不安全

如果上面代码没有逃逸闭包,那么传入一个inout Int 类型就没问题了。setTimePicker2方法在执行的时候同时更改selectRow这个Int数据

解决方法

创建一个类,用类包裹基础数据类型Int这个类只用来存选中行数,这个类只用来存选中行数,因为直接用基础数据类型inout int,不能在里面再调用逃逸闭包@escaping,但是参数传入类的对象,是直接操作对象里面的成员,操作的地址相同。

class TimeVSelected:NSObject{var selectRow : Int = 0
}

函数定义成这样,参数列表里面要类对象TimeVSelected,原来Int类型的地方用 selectobj.selectRow 对象的成员变量来代替

    func setTimePicker(selectobj:  TimeVSelected,label:UILabel){//注意这里用selectobj.selectRow代替之前的selectRowlet vc = TDWPickerVC(items: timeItems, titleLabelStr: "请选择时间段",selectRow: selectobj.selectRow) {print("点击取消")} confirmBlock: { (str,row) inprint("点击确定",str)selectobj.selectRow = rowprint("selectobj地址是:",selectobj)label.text = str}vc.modalPresentationStyle = .customvc.modalTransitionStyle = .crossDissolvenavigationController?.present(vc, animated: true, completion: nil)}

容易产生的问题

之前我也试过,既然类对象可以直接修改里面的对象,inout 和 @escaping不能一起用,那我为什么不能直接去掉inout这样设置参数列表:

 func setTimePicker2(selectRow:Int,label:UILabel) 

这样会报错,因为函数参数是不能在函数体里面改变的,函数参数被认为是let常量,如下:报错

func setTimePicker2(selectRow:Int,label:UILabel){let vc = TDWPickerVC(items: timeItems, titleLabelStr: "请选择时间段",selectRow: selectRow) {print("点击取消")} confirmBlock: { (str,row) inprint("点击确定",str)selectRow = row //这里会报错Cannot assign to value: 'selectRow' is a 'let' constantlabel.text = str}print("time1VSelectRow=",selectRow )vc.modalPresentationStyle = .customvc.modalTransitionStyle = .crossDissolvenavigationController?.present(vc, animated: true, completion: nil)}

xcode截图如下:
在这里插入图片描述
我们用类对象在函数体也不能改变,但是对象成员可以改变,看我下面的截图,报错也是说对象是let类型不能改:

 func setTimePicker(selectobj:  TimeVSelected,label:UILabel){let vc = TDWPickerVC(items: timeItems, titleLabelStr: "请选择时间段",selectRow: selectobj.selectRow) {print("点击取消")} confirmBlock: { (str,row) inprint("点击确定",str)selectobj.selectRow = rowselectobj = TimeVSelected()//这里就会报错,因为selectobj是函数参数,不能赋值print("selectobj地址是:",selectobj)label.text = str}vc.modalPresentationStyle = .customvc.modalTransitionStyle = .crossDissolvenavigationController?.present(vc, animated: true, completion: nil)}

在这里插入图片描述
以前用C++的时候这种函数参数列表里的参数叫形参,是可以改的,但是改完以后,不会影响函数传入之前的值,形参是临时变量,函数结束就释放了,swift就不一样,类对象作为函数参数,实际就是把类对象地址传过来,跟c++一样,改变对象里成员值,对象也被改变

print("timeVselected1地址是:",timeVselected1)

通过打印证明函数参数的类对象传递和C++的地址传递一样,函数外和内部都是一个地址
在这里插入图片描述

总结

以后再需要传递那种在函数里改变函数外的值,恰好函数内部有逃逸闭包@escaping的,就用类对象传递到函数中,再改变类对象的成员,这样就能在函数内改变函数外的值了。


http://chatgpt.dhexx.cn/article/5A7B0HhA.shtml

相关文章

Using the “escape“ directive (legacy escaping) is not allowed when auto-escaping is on with a markup

springboot 2.3.0版本以上&#xff0c;springboot自动引用freemarker模板文件的后缀从.ftl变成了.ftlh <!DOCTYPE html> <#escape x as x?html> <#include "../common/macro.ftl"> <html lang"en"> </html> </#escape&…

Escaping closure captures non-escaping parameter ‘xx‘

新版的Swift闭包做参数默认是noescaping&#xff0c;不再是escaping。 如果函数里执行该闭包&#xff0c;要添加escaping。

Swift中的逃逸闭包(@escaping )与非逃逸闭包(@noescaping)

逃逸闭包 概念&#xff1a;一个接受闭包作为参数的函数&#xff0c;该闭包可能在函数返回后才被调用&#xff0c;也就是说这个闭包逃离了函数的作用域&#xff0c;这种闭包称为逃逸闭包。当你声明一个接受闭包作为形式参数的函数时&#xff0c;你可以在形式参数前写escaping来…

VMware创建Linux虚拟机之(三)Hadoop安装与配置及搭建集群

Hello&#xff0c;world&#xff01; &#x1f412;本篇博客使用到的工具有&#xff1a;VMware16 &#xff0c;Xftp7 若不熟悉操作命令&#xff0c;推荐使用带GUI页面的CentOS7虚拟机 我将使用带GUI页面的虚拟机演示 虚拟机&#xff08;Virtual Machine&#xff09; 指通过…

hadoop安装及简单的使用

hadoop安装及简单的使用 一、hadoop运行环境搭建二、hadoop 目录结构三、hadoop 本地模式四、hadoop 伪分布式模式五、伪分布式 YARN 运行六、伪分布式启动历史服务器七、伪分布式配置日志的聚集八、hadoop 集群模式 一、hadoop运行环境搭建 1.环境准备 安装 hadoop 需要使用 …

hadoop安装(window10)

一、下载和winutils 1.下载&#xff1a;http://archive.apache.org/dist/hadoop/core/ 官网下载&#xff1a;http://hadoop.apache.org/releases.html &#xff08;提供最新的几个版本&#xff09; https://github.com/steveloughran/winutils&#xff08;windows安装需要&…

Hadoop安装与配置

第一步&#xff1a;装虚拟机 我把hadoop安装需要的文件放在下面大家自行去取&#xff1a; 百度网盘 请输入提取码 提取码&#xff1a;8888 由于centos镜像文件太大传不上去需要的话可以加我qq:364960241 目录 第一步&#xff1a;装虚拟机 第二步&#xff1a;配置静态网络…

基于CentOS虚拟机的Hadoop安装教程(自用备忘)

该博文是用于记录Hadoop的安装过程&#xff0c;且记录其中出现的一些问题&#xff0c;防止日后遗忘 实验环境&#xff1a; 虚拟机&#xff1a;CentOS7Hadoop&#xff1a;3.3.2java&#xff1a;java 8u331下载连接&#xff1a; CentOS&#xff1a;centos-7-x86_64-dvd-2009.iso…

Hadoop安装与配置详细教程

【确保服务器集群安装和配置已经完成&#xff01;】 前言 请根据读者的自身情况&#xff0c;进行相应随机应变。 我的三台CentOS7服务器&#xff1a; 主机&#xff1a;master&#xff08;192.168.56.110&#xff09; 从机&#xff1a;slave0&#xff08;192.168.56.111&…

Hadoop安装教程 Linux版

Hadoop安装教程 Linux版 一、Linux虚拟机安装 方法一&#xff1a;使用Windows下Linux子系统&#xff08;大佬可选&#xff09; 方法二&#xff1a;使用VMware安装Linux虚拟机&#xff08;小白可选&#xff09; 方法三&#xff1a;安装双系统&#xff08;不怕麻烦的可以试试&am…

Ubuntu下的Hadoop安装

二、Hadoop安装 采用版本为hadoop-2.7.7 ①JDK的安装 2.1.1 创建文件夹 sudo mkdir /expt sudo chmod 777 /expt 这个出错我参考别的原因也改过来了&#xff0c; pkexec chmod 0440 /etc/sudoers 2.1.2 移动文件 之前已经解压过了&#xff0c;所以改一下位置就行了 2.1.3 创…

hadoop 安装与测试

1、下载安装包 登录官网hadoop.apache.org 下载安装包 版本可以根据自己的需求进行选择 本文需要下载的安装包是&#xff1a;Hadoop-3.1.3.tar.gz / jdk-14_linux-x64_bin.tar.gz 将Windows上的安装包上传到Linux上&#xff0c;方式有很多。本文是将安装包通过共享文件夹形式…

Hadoop安装目录

/root/software/hadoop-2.6.0-cdh5.15.1/etc/hadoop第一步骤 vi core-site.xml <configuration> <property> <name>fs.defaultFS</name> <value>hdfs://hadoop000:8020</value> </property> <property> <name>hadoop.t…

hadoop安装常见问题

目录 SSH服务器拒绝了密码。请再试一次​ ubuntu修改登陆用户名 这样ftp成功链接ubuntu 现在的ubuntu支持直接拖拽文件传输&#xff0c;不用ftp的 yarn是什么 linux配置java环境变量 hadoop安装包下载 linux不能编辑sshd_cofig SSH的简单理解和运用 SSH服务器拒绝了密…

hadoop安装流程

这篇文章主要记录安装hadoop的过程&#xff0c;给后来者一点帮助&#xff0c; 官网获取安装包 选一款你想要的 Apache Hadoop 下载完成后上传到服务器&#xff08;我用的是finalshell&#xff09; 先别急着解压 准备Java包 像上面一样官网下载对应的Java包 这边我已经准…

hadoop安装

hadoop安装 安装模板虚拟机 1) 设置虚拟机IP地址 2) 设置windows虚拟地址 3) 修改OS的IP地址 [roothadoop100 ~]# vim /etc/sysconfig/network-scripts/ifcfg-ens33BOOTPROTOstatic IPADDR # 自己的ip GATEWAY # 自己的网关地址 DNS1 # 自己的dns地址# 一定不要有空格!不要有…

Hadoop 安装与配置

创建虚拟机 这里需要下载ubuntu操作系统 创建一个hadoop用户&#xff0c;并使用/bin/bash 作为shell 虚拟机打开成功后&#xff0c;打开终端Terminal&#xff0c;开始创建hadoop用户 sudo useradd -m hadoop -s /bin/bash 为hadoop设置一个密码 sudo passwd hadoop 为后续操作方…

Hadoop 安装部署

官网下载软件&#xff1a; Ubuntu : https://releases.ubuntu.com/ jdk &#xff1a; https://www.oracle.com/java/technologies/downloads/ Hadoop &#xff1a; https://archive.apache.org/dist/hadoop/common/hadoop-3.3.2/ 下载后上传到服务器&#xff0c;解压 一 1. …

Hadoop的安装与配置(非常重要)

官方的原生配置文档Hadoop3.1.0 HDFS的组成 NameNodesecondaryNameNodeDataNode 这是以主从模式来运行的&#xff0c;前两个在maser节点上&#xff0c;最后一个在slave节点上 1. 解压hadoop安装包 要学会从官方网站里找到历史镜像和release的发布版本来下载 我觉得从别人给的…

hadoop安装教程(一次填完所有的坑)

文章目录 01 引言02 hadoop 安装2.1 下载与安装2.2 hadoop配置2.3 免登陆配置2.4 配置环境变量2.5 配置域名2.6 启动 03 相关命令 3.1 yarn相关命令 3.2 hdfs相关命令 04 一次填完所有的坑05 Yarn相关配置06 文末 01 引言 最近安装hadoop-2.7.7 版本的时候遇到了很多坑&#x…