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

【iOS】多界面传值

目录

属性传值(正向传值)

协议传值

通知传值

block传值

KVO传值


在iOS中的页面传值方式主要以下六种:

  1. 属性传值
  2. 单例传值
  3. NSUserDefault传值
  4. 代理传值
  5. block传值

属性传值(正向传值)

属性传值是通过定义属性并设置值来实现数据传递的方式,多用于前一个页面向后一个页面传值。

我们现在要跳转的第二个页面设置属性值

@property (nonatomic, strong) NSString *username;

在原来的页面创建B的实例,然后直接给他赋值,然后后一个页面就能拿到前一个页面的数值了

BViewController *bVC = [[BViewController alloc] init];
bVC.username = @"小明";
[self.navigationController pushViewController:bVC animated:YES];

在天气预报中,本人就使用了这种传值,效果如下

协议传值

协议传值是通过定义协议和代理方法,在不同页面之间传递数据。多用于后一个页面向前一个页面回传。在3gshare中,我们就假日详情页向首页传值就用到了这个。相当于上一个动图的反向。

我们先在需要传输信息的页面定义协议:其中包括需要传递的数据的代理方法

然后在发送数据的视图控制器的头文件声明代理属性,保存代理对象。

触发代理方法:

在发送数据的视图控制器中,在适当的时机,触发代理方法,并将需要传递的数据作为参数传递给代理方法

然后在接收的视图控制器中实现方法:

- (void)holidayDetail:(HolidayDetailViewController *)detaildidChangeLikeStatus:(BOOL)isLikednewLikeCount:(NSInteger)likeCount
{NSMutableDictionary *item = [self.dataArray[0] mutableCopy];item[@"isLiked"] = @(isLiked);item[@"likeCount"] = @(likeCount);[self.dataArray replaceObjectAtIndex:0 withObject:item];NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:1];[self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
}

最后把后面VC的代理设为前一个VC,让后一个为前一个代理。

通知传值

创建并发送通知:
首先,在发送者对象中创建一个通知,并指定通知的名称(通常使用字符串来表示)。可以通过NSNotification类或NSNotificationName宏来创建通知。需要传递信息给其他对象时,可以通过NSNotificationCenter的postNotificationName:object:userInfo:方法来发送通知。在发送通知时,可以附带一些额外的信息(如字典)作为通知的userInfo参数。

然后,我们需要注册观察者:

接收通知:
接收者对象需要实现一个方法,用于处理接收到的通知。这个方法是在观察者注册时通过selector参数指定的。当通知被发送时,通知中心会调用这个方法,并传递相关的信息给观察者。

最后,我们别忘了移除观察者,将其从通知中心移除,避免内存泄露。

block传值

在iOS开发中,可以使用Block(闭包)进行值的传递和回调操作。Block是一种封装了一段代码的对象,可以在需要的时候执行该代码块。
其基本步骤如下:

1. 在后一个页面定义一个Block属性

@property (nonatomic, copy) void(^reutnblock)(NSString* temp, NSInteger num);

2.  设置一个时间来触发返回上一级视图控制器的时候,使用第一步定义的block,把需要传递的放在^blcok中间

-(void)press{self.reutnblock(self.label.text, --_tag); // 重点部分[self.navigationController popViewControllerAnimated:YES];}

3. 在前一个页面跳转到后一个页面的事件函数中,调用后一个页面的Block这个属性

-(void)press {secondViewController* second = [[secondViewController alloc] init];second.reutnblock = ^(NSString * _Nonnull temp, NSInteger num) {self.label.text = temp;self.num = num;};[self.navigationController pushViewController:second animated:YES];
}

优点

Block提供了一种灵活的方式,可以封装一段代码并在需要的时候执行。这使得值传递的逻辑可以根据具体需求进行定制和扩展。
Block可以用于异步操作,例如在网络请求完成后执行回调操作。这样可以实现非阻塞的异步编程模式,提高代码的响应性和用户体验。
缺点

使用Block时,需要注意对循环引用和内存泄漏的处理。Block可能会持有其所捕获的变量和对象,如果不正确地处理循环引用,可能会导致内存泄漏。
较复杂的Block可能会导致代码变得难以理解和维护。由于Block可以封装任意代码逻辑,过度复杂或嵌套的Block可能会降低代码的可读性和可维护性。
 

block传值我目前还没在项目中实际使用过,以后在项目中的具体应用我会继续补充在博客中

KVO传值

概述

KVO全称KeyValueObserve也就是观察者模式,是apple提供的一套事件通知机制.允许对象监听另一个对应特殊属性的改变,并在改变时接受到该事件.一般继承自NSObject的对象都默认是支持KVO。

KVO(Key-Value-Observing,键值观察),即观察关键字的值的变化。首先在子页面中声明一个待观察的属性,在返回主页面之前修改该属性的值。在主页面中提前分配并初始化子页面,并且注册对子页面中对应属性的观察者。在从子页面返回主页面之前,通过修改观察者属性的值,在主页面中就能自动检测到这个改变,从而读取子页面的数据。KVO只对属性发生作用。

传递方向

主要也是从后往前。

1.注册观察者

@property (nonatomic, strong) secondViewController* second; //这里现在第一个页面中设置第二个页面作为自己的一个属性
- (void)press { //这里我才用了一个按钮来触发事件//[self willChangeValueForKey:@"ary"];self.second = [[secondViewController alloc] init];[self.second addObserver:self forKeyPath:@"userName" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];[self.navigationController pushViewController:self.second animated:YES];
}

observer: 这是观察者对象,即要接收属性变化通知的对象。通常是当前视图控制器或其他感兴趣的对象。
keyPath: 要监听的属性的名称,以字符串表示。当该属性的值发生变化时,KVO 就会通知观察者。
options: 一个枚举值,用于指定监听的选项。这个参数可以设置为多个选项的组合,使用按位或(|)进行连接。常见的选项有:
NSKeyValueObservingOptionNew: 当属性的值发生变化时,提供新的属性值作为通知的参数。
NSKeyValueObservingOptionOld: 当属性的值发生变化时,提供旧的属性值作为通知的参数。
NSKeyValueObservingOptionInitial: 在添加观察者时,立即发送一次通知,提供当前属性的值作为通知的参数。
NSKeyValueObservingOptionPrior: 在属性值发生实际变化之前,先发送一次通知,提供旧的属性值作为通知的参数。
context: 这是一个指针类型的参数,用于传递额外的上下文信息。通常情况下可以传入 NULL,表示不需要传递上下文信息。如果你需要在观察者中处理一些额外的信息,可以使用自定义的指针类型来传递数据。

2.实现监听方法

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {if ([keyPath isEqualToString:@"userName"]) {self.label.text = self.second.userName;NSLog(@"old text:%@   new text:%@", [change objectForKey:NSKeyValueChangeOldKey], [change objectForKey:NSKeyValueChangeNewKey]);}
}

3.移除观察者

- (void)dealloc {[self removeObserver:self forKeyPath:@"userName"];
}

tips

这种方式不可以实现对于数组元素的一个监听,因为KVO是对于setter方法的监听,而数组的addObject方法并不是setter方法的内容,所以无法通过上述方法实现对于数组的一个监听。

不使用时要移除KVO

http://www.xdnf.cn/news/1485397.html

相关文章:

  • 灾难性遗忘:神经网络持续学习的核心挑战与解决方案
  • CSS(展示效果)
  • 全面解析3DMAX景观建模材质处理方法
  • Unity Transparent透明材质透明度为1时的穿透显示问题
  • 【jenkins】--安装部署
  • MyBatis 拦截器让搞定监控、脱敏和权限控制
  • KMeans聚类
  • 项目介绍:图像分类项目的最小可用骨架--代码细节讲解
  • 关于学习的一些感悟
  • HTTP原理
  • Archon01-项目部署
  • SQLAlchemy ORM-表与表之间的关系
  • Python快速入门专业版(九):字符串进阶:常用方法(查找、替换、分割、大小写转换)
  • Text2Sql.Net架构深度解析:从自然语言到SQL的智能转换之道
  • 2025算法八股——大模型开发——指令微调
  • 跳转原生系统设置插件 支持安卓/iOS/鸿蒙UTS组件
  • 安卓学习 之 ProgressBar(进度条)控件
  • Android 热点开发的相关api总结
  • Python-LLMChat
  • 《数据结构全解析:栈(数组实现)》
  • Dockerfile解析器指令(Parser Directive)指定语法版本,如:# syntax=docker/dockerfile:1
  • 【Java实战㉛】解锁Spring框架实战:深入IOC容器的奇妙之旅
  • 从0开始制做一个Agent
  • CMake构建和调试简单程序(windows)
  • YOLO11实战 第009期-基于yolo11的咖啡叶病害目标检测实战文档(yolo格式数据免费获取)
  • C++进阶——多态
  • 简述ajax、node.js、webpack、git
  • ncnn-Android-mediapipe_hand 踩坑部署实录
  • 【数据结构】经典 Leetcode 题
  • Java安全体系深度研究:技术演进与攻防实践