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

【OC】多界面传值总结

【OC】多界面传值总结

文章目录

  • 【OC】多界面传值总结
    • 属性传值(A->B)
    • 代理传值(B->A)
    • Block传值(B->A)
    • 通知传值(任意方向)
    • KVO传值(观察属性变化)

在学习iOS 开发的知识过程中,把几种常见的多界面传值方式梳理了一下,记录在这里,方便以后回顾

属性传值(A->B)

这是一种正向传值,也是最简单的一种,就是从 A 界面跳转到 B 界面的时候,把数据直接塞给 B

思路:在 B 控制器里定义一个属性,跳转之前给它赋值,B 拿到之后用就行了

// SecondViewController.h#import<UIKit/UIKit.h>@interfaceSecondViewController:UIViewController@property(nonatomic,copy)NSString*receiveStr;@end
// SecondViewController.m-(void)viewDidLoad{[superviewDidLoad];// 直接用 receiveStr 就行NSLog(@"%@",self.receiveStr);self.titleLabel.text=self.receiveStr;}
// FirstViewController.m-(void)jumpToSecond{SecondViewController*secondVC=[[SecondViewController alloc]init];secondVC.receiveStr=@"我是从第一个界面传来的";[self.navigationController pushViewController:secondVC animated:YES];}

这个最简单,正向传没啥问题,但是反向传(B → A)就不行了

代理传值(B->A)

这是一种反向传值,比如从 B 把数据传回给 A

思路:B 里面定义一个协议,A 来遵守这个协议,B 在需要传值的时候调用代理方法,A 实现这个方法拿数据

FirstViewController.m

// 遵守协议@interfaceFirstViewController()<SecondVCDelegate>@end// 跳转的时候设置代理-(void)jumpToSecond{SecondViewController*secondVC=[[SecondViewController alloc]init];secondVC.delegate=self;[self.navigationController pushViewController:secondVC animated:YES];}// 实现代理方法-(void)sendData:(NSString*)data{NSLog(@"B 传回来的数据:%@",data);self.label.text=data;}

SecondViewController.h

#import<UIKit/UIKit.h>// 定义协议@protocolSecondVCDelegate<NSObject>-(void)sendData:(NSString*)data;@end@interfaceSecondViewController:UIViewController// 代理属性,用 weak 防止循环引用@property(nonatomic,weak)id<SecondVCDelegate>delegate;@end

SecondViewController.m

// 点击按钮传值回去-(void)sendBtnClick{if([self.delegate respondsToSelector:@selector(sendData:)]){[self.delegate sendData:@"这是从 B 传回来的数据"];}[self.navigationController popViewControllerAnimated:YES];}

Block传值(B->A)

Block 传值和代理传值效果差不多,也是反向传,但是写起来比代理简洁很多

思路:B 里面定义一个 block 属性,A 跳转到 B 之前给这个 block 赋值(实现具体逻辑),B 在合适的时候调用这个 block 把数据传出去

SecondViewController.h

#import<UIKit/UIKit.h>// 定义 block 类型typedefvoid(^SendDataBlock)(NSString*data);@interfaceSecondViewController:UIViewController@property(nonatomic,copy)SendDataBlock sendBlock;@end

SecondViewController.m

-(void)sendBtnClick{// 调用 block 传数据if(self.sendBlock){self.sendBlock(@"这是 Block 传回来的数据");}[self.navigationController popViewControllerAnimated:YES];}

FirstViewController.m

-(void)jumpToSecond{SecondViewController*secondVC=[[SecondViewController alloc]init];// 给 block 赋值,在这里写好回调逻辑secondVC.sendBlock=^(NSString*data){NSLog(@"Block 收到数据:%@",data);self.label.text=data;};[self.navigationController pushViewController:secondVC animated:YES];}

⚠️注意循环引用!

block 里面用了self,如果secondVC也强引用了 A,就会形成循环引用,所以最好通过弱引用打破循环引用:

__weaktypeof(self)weakSelf=self;secondVC.sendBlock=^(NSString*data){NSLog(@"Block 收到数据:%@",data);weakSelf.label.text=data;};

通知传值(任意方向)

通知这个机制比较灵活,不只是两个界面之间,一对多都可以

适合那种不好直接建立联系的两个模块之间通信

思路:发通知的地方 post,监听的地方 addObserver,然后处理就行

接收方(比如 A)先注册监听

-(void)viewDidLoad{[superviewDidLoad];// 注册通知[[NSNotificationCenter defaultCenter]addObserver:selfselector:@selector(receiveNotification:)name:@"SendDataNotification"object:nil];}// 接收到通知的处理方法-(void)receiveNotification:(NSNotification*)noti{NSString*data=noti.userInfo[@"data"];NSLog(@"收到通知,数据是:%@",data);self.label.text=data;}// 记得移除,不然会出问题-(void)dealloc{[[NSNotificationCenter defaultCenter]removeObserver:self];}

发送方(B)发通知

-(void)sendBtnClick{NSDictionary*userInfo=@{@"data":@"这是通知传过来的数据"};[[NSNotificationCenter defaultCenter]postNotificationName:@"SendDataNotification"object:nil userInfo:userInfo];}

但是通知滥用的话代码逻辑会很乱,不好追踪,所以能用代理就用代理,通知用来处理那种"远距离"的通信

KVO传值(观察属性变化)

KVO(Key-Value Observing)严格来说不算"传值",更像是观察某个对象属性的变化,当被观察的属性值改变时,观察者会自动收到通知

思路:A 观察 B 的某个属性,B 的属性一变,A 就知道了。

被观察的对象(B 里有一个属性)

// SecondViewController.h@property(nonatomic,copy)NSString*observeStr;

A 添加观察

-(void)viewDidLoad{[superviewDidLoad];// 假设 self.secondVC 是持有的 B 对象[self.secondVC addObserver:selfforKeyPath:@"observeStr"options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];}// 属性变化时会调这个方法-(void)observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object change:(NSDictionary*)change context:(void*)context{if([keyPath isEqualToString:@"observeStr"]){NSString*newValue=change[NSKeyValueChangeNewKey];NSLog(@"observeStr 变了,新值是:%@",newValue);}}// 移除观察,不然会崩-(void)dealloc{[self.secondVC removeObserver:selfforKeyPath:@"observeStr"];}

B 那边改属性值

// 直接改,KVO 会自动触发self.observeStr=@"新的数据";

KVO 感觉平时用的不多,一般在需要监听 model 属性变化的时候会用,界面传值用这个稍微有点绕

实际开发中,正向传值一般用属性,反向传值优先考虑 Block,需要一对多广播的用通知,KVO 更多用在数据层的监听,代理也很常用,特别是 UIKit 里的那些系统组件基本都是代理模式

以上是自己的一些理解,如果有说错的地方欢迎指正

http://www.jsqmd.com/news/761795/

相关文章:

  • 别让高功率激光烧坏你的镜头!一文搞懂LIDT(激光损伤阈值)怎么选
  • 如何一劳永逸解决Windows和Office激活问题?KMS智能激活终极指南
  • 开源鼠标增强工具MousePal:手势识别与按键重映射实战指南
  • 2026年甘肃亮化工程权威厂家TOP5:兰州路灯工程/兰州道路照明工程/兰州发光字/兰州商业街区泛光照明/兰州太阳能路灯/选择指南 - 优质品牌商家
  • 为什么你的PHP订单系统总在凌晨三点告警?资深架构师亲授6步根因定位法
  • MAXQ JTAG板固件更新全流程与常见问题解析
  • AI 系统上线后模型列表空白的稳定性治理:从缓存失效到分层兜底的工程实践
  • 拆解Simulink导弹模型:自动驾驶仪设计、导引头建模与Stateflow制导逻辑详解
  • 智能体编排框架agents-flex:构建复杂AI系统的柔性骨架
  • TPFanCtrl2终极指南:如何彻底掌控ThinkPad风扇,打造静音高效的散热系统
  • 嵌入式实时调度算法与分区技术解析
  • R 4.5量化回测黄金标准白皮书(2024 Q2更新):涵盖IS/OS划分规范、滚动窗口长度最优解(基于信息熵最小化)、及监管沙盒验证模板
  • 别再截图了!用Mathpix API+Python脚本,5分钟批量识别100份数学试卷公式
  • 3步解锁你的Switch:TegraRcmGUI完整免费教程
  • Yume1.5:基于文本控制的3D世界生成技术解析
  • Scikit-LLM:将大语言模型无缝集成到Scikit-learn工作流
  • 高中数学教资面试教案设计:用这个万能模板套用《函数单调性》等高频课题
  • IT资产管理系统是什么?其主要的数字化特征与智能监控功能有哪些?
  • Neovim集成MCP协议:构建AI智能体开发工作流
  • 基于Python的微信公众号监控工具:原理、部署与反爬策略实践
  • 基于Next.js与OpenAI API构建开源ChatGPT Web界面全解析
  • 长期使用中我们对Taotoken平台API稳定性的实际感受
  • Ubuntu全线宕机超24小时:亲伊朗组织DDoS与CVE-2026-31431 PoC公开的致命交汇
  • 从芯片手册到AutoSar代码:手把手教你为STM32配置片内/片外看门狗(含WdgIf抽象层详解)
  • 基于大语言模型的自然语言转SQL工具:从原理到企业级实践
  • QrScan:构建高效离线二维码批量识别系统的技术实践
  • 别再乱调路由器了!手把手教你根据家里设备选对WiFi频段(2.4G/5G/6G)和信道
  • Video-CoE框架:基于事件链建模的视频预测技术
  • 日期间隔匹配的SAS实例解析
  • 融合知识图谱与BERT的智能问答机器人设计:从原理到落地实践