当前位置: 首页 > news >正文

iOS——Block回调

先跟着我实现最简单的 Block 回调传参的使用,如果你能举一反三,基本上可以满足了 OC 中的开发需求。已经实现的同学可以跳到下一节。

首先解释一下我们例子要实现什么功能(其实是烂大街又最形象的例子):

有两个视图控制器 A 和 B,现在点击 A 上的按钮跳转到视图 B ,并在 B 中的textfield 输入字符串,点击 B 中的跳转按钮跳转回 A ,并将之前输入的字符串

显示在 A 中的 label 上。也就是说 A 视图中需要回调 B 视图中的数据。
Pasted image 20230623170202.png

Pasted image 20230623170242.png

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AjEpWjSQ-1690945668053)(https://raw.githubusercontent.com/ArnoVD97/PhotoBed/master/photo202307281507212.png)]

block回调传值是一个从后面向前传递值的一个过程,这个即这个块应该定义在B页面内,重命名一个块,你会的到两个函数,一个是块函数,一个是回调函数,我们的网络请求用的就是block回调传值在网络请求中的manager就使用的是回调函数充当B页面,而需要调用数据的页面使用块,可以获得回调函数中的数据,

    BVC.callBackData(NSString  _Nonnull data#);
//回调函数(传值函数)用用于传入回调数据BVC.callBackData = ^(NSString  _Nonnull data)//普通的块,他会调用回调函数来获取里面的数据//BViewController.h
#import <UIKit/UIKit.h>typedef void(^CallBackBlcok) (NSString *text);//1@interface BViewController : UIViewController@property (nonatomic,copy)CallBackBlcok callBackData;//2
@end

在这里,代码 1 用 typedef 定义了 void(^) (NSString *text)的别名为 CallBackBlcok 。这样我们就可以在代码 2 中,使用这个别名定义一个 Block 类型的变量 callBackBlock

在定义了 callBackBlock 之后,我们可以在 B 中的点击事件中添加 callBackBlock 的传参操作:


//BViewController.m- (IBAction)click:(id)sender {self.callBackBlock(_textField.text); //1[self.navigationController popToRootViewControllerAnimated:YES];
}

这样我们就可以在想要获取数据回调的地方,也就 A 的视图中调用 block:


// AViewController.m
- (IBAction)push:(id)sender {BViewController *bVC = [self.storyboard instantiateViewControllerWithIdentifier:@"BViewController"];bVC.callBackBlock = ^(NSString *text){ // 1NSLog(@"text is %@",text);self.label.text = text;};[self.navigationController pushViewController:bVC animated:YES];
}

代码 1 中,通过对回调将 B 中的数据传递到代码块中,并赋值给 A中的 label,实现了整个回调过程。

上例是通过将 block 直接赋值给 block 属性,也可以通过方法参数的方式传递 block 块。

Block 的疑惑

到目前为止,一切看起来都很美好(如果你照着上面的例子做的话),功能正常, A 视图中也获取到数据了。但是某些人可能就要说了,你的代码有问题,你的思路有问题,你这是误人子弟。

是的,代码的确还有问题,第一个问题就是循环引用的问题,在 A 视图的block 代码块中:


bVC.callBackBlock = ^(NSString *text){NSLog(@"text is %@",text);  self.label.text = text;  };

代码 self.label.text = text; ,在 Block 中引用 self ,也就是 A ,而 A 创建并引用了 B ,而 B 引用 callBackBlock,此时就形成了一个循环引用,而编译器也不会报任何错误,我们需要非常小心这个问题(面试百分百问到我会乱说?)。此时我们通常的解决方法是使用弱引用来解除这个循环:

__weak AViewController *weakSelf = self;bVC.callBackBlock = ^(NSString *text){ NSLog(@"text is %@",text); 
//  self.label.text = text; weakSelf.label.text = text;};

第二个问题是我自己对 Block 的理解不到位,我们都知道 Block 能截取自动变量,并且是不能在 Block 块中进行修改的(除非用__block修饰符),但是很明显 weakSelf.label.text的值被修改了,并且没有用__block修饰符, 这是为什么呢?因为 label 是个全局变量,而如果像如下的局部变量 a 是不能修改的,编译器也会报错:


局部变量

通过这个小例子发现的两个问题,也算是值得了。

为什么能实现回调

回顾一下我们在 B 中所实现的代码,不外乎定义了一个 Block 变量,并在适当的时候传入参数,那么为什么在调用了 self.callBackBlock(_textField.text) 之后,值就神奇传到了 A 中的 Block 块了呢?
通过简单的整理我们可以发现完整的回调流程应该是这样的:
Pasted image 20230623172613.png

当将一个 Block 代码块赋值给 bVC.callBackBlock 后,callBackBlock 的指针就指向了这个 Block 代码块。之后,可以通过调用 callBackBlock(NSString *text) 来执行这个 Block 代码块,并实现回调功能。

// 定义一个 Block 代码块
void (^myBlock)(NSString *text) = ^(NSString *text) {// 执行一些代码NSLog(@"%@", text);
};// 将 Block 代码块赋值给 callBackBlock
bVC.callBackBlock = myBlock;// 调用 callBackBlock,执行回调
if (bVC.callBackBlock) {bVC.callBackBlock(@"Hello, World!");
}

我按照我的理解说一下这个流程,如果没有回调函数那么这个block代码块不会被运行
只有运行到B页面的时候,使用了回调函数,才会执行block代码块里面的内容,回调函数的作用是调用这个匿名函数,并且传回一个值给我们使用的block代码块

// 声明一个带有回调参数的方法
- (void)performOperationWithCompletion:(void (^)(NSString *result))completion {// 执行一些操作NSString *result = @"Operation completed";// 调用回调Block并传递结果if (completion) {completion(result);}
}// 调用带有回调参数的方法
[self performOperationWithCompletion:^(NSString *result) {NSLog(@"Result: %@", result);
}];

如果像这样使用方法来调用的话,在方法实现需要要使用回调函数,然后回跳转到调用该方法的地方,继续执行block块里面的的内容。

http://www.lryc.cn/news/108686.html

相关文章:

  • html学习6(xhtml)
  • UML-活动图
  • 跨境电商怎么做?Live Market教你创业及做大生意
  • Linux 4.19 和Linux 5.10 的区别
  • 学习单片机的秘诀:实践与坚持
  • Hum Brain Mapp:用于功能连接体指纹识别和认知状态解码的高精度机器学习技术
  • Ajax图书管理业务
  • 对于爬虫代码的优化,多个方向
  • ffmpeg推流卡顿修复
  • Java02-迭代器,数据结构,List,Set ,TreeSet集合,Collections工具类
  • 离散 Hopfield 神经网络的分类与matlab实现
  • opencv 30 -图像平滑处理01-均值滤波 cv2.blur()
  • 中小企业的数字化营销应该如何着手?数字化营销到底要怎么做?
  • 实数信号的傅里叶级数研究(Matlab代码实现)
  • oracle数据库巡检脚本
  • 服务注册中心consul的服务健康监控及告警
  • 【算法第十四天7.28】二叉树的最大深度,二叉树的最小深度 ,完全二叉树的节点个数
  • 网络安全设备-等保一体机
  • Kafka的配置和使用
  • 【C++】unordered_map在Windows和Linux上的不同行为
  • Apipost三方消息通知,接口变更不用愁
  • C语言 用数组名作函数参数
  • 每日一题(980. 不同路径 III)-回溯
  • 【Python:json常用函数,用于加载和保存json文件】load(), loads(), dump(), dumps()
  • Flink State 和 Fault Tolerance详解
  • 小红书2023“家生活”趋势白皮书
  • 使用 LangChain 搭建基于 Amazon DynamoDB 的大语言模型应用
  • 210. 课程表 II Python
  • 【LeetCode 算法】Linked List Cycle II 环形链表 II
  • 蒸散发与植被总初级生产力估算