【iOS】多界面传值(五大传值方式)
【iOS】多界面传值(五大传值方式)
文章目录
- 【iOS】多界面传值(五大传值方式)
- 属性传值(Property)
- 协议传值(Delegation)
- 通知传值(NSNotification)
- Block传值
- 单例(Singleton)
- 总结
属性传值(Property)
属性传值是一种正向传值的方式,即通过访问后一个视图控制器的属性,通过这个属性从前一个界面向后一个界面进行传值
我们直接讲解其步骤:
-
首先在后一个界面的.h文件定义属性
@interface TargetViewController : UIViewController@property NSString* PropertyRecieved;@end
-
之后在前一个界面对当后一个界面将弹出时对这个属性进行复刻
TargetViewController *targetVC = [[TargetViewController alloc] init]; targetVC.PropertyRexieved = @"Hello, World!"; [self.navigationController pushViewController:targetVC animated:YES];
协议传值(Delegation)
也称作代理传值,与属性传值相反,这是一种反向传值的方法,将后一个界面传值给前一个界面,本质是用协议中定义的方法来进行传值的
-
先要在后一个界面定义一个用于传值的协议与其代理属性
// BViewController.h@protocol BViewControllerDelegate <NSObject> - (void)didReceiveData:(NSString *)data; @end@interface BViewController : UIViewController@property (nonatomic, weak) id<BViewControllerDelegate> delegate;@end
-
在前一个视图中遵守协议,设置代理并实现代理的方法,在后一个界面触发回调
// AViewController.h #import "BViewController.h"@interface AViewController : UIViewController <BViewControllerDelegate> @end// AViewController.m BViewController *bVC = [[BViewController alloc] init]; bVC.delegate = self; [self.navigationController pushViewController:bVC animated:YES];- (void)didReceiveData:(NSString *)data {NSLog(@"收到数据:%@", data); }
// BViewController.m (传值的时候触发) if ([self.delegate respondsToSelector:@selector(didReceiveData:)]) {[self.delegate didReceiveData:@"我是传回来的数据"]; }
通知传值(NSNotification)
通知传值是通过NSNotificationCenter实现的广播机制,一处发出了消息,任何监听这个消息的地方都可以收到,一般适合多个界面或者模块之间的状态同步
-
注册监听者,一旦有人发出名为"DarkModeChanged"的通知,就执行selector中的方法
[[NSNotificationCenter defaultCenter] addObserver:selfselector:@selector(handleDarkModeChange:)name:@"DarkModeChanged"object:nil];
-
发送通知,在源视图中进行通知的发送,userInfo即为所要传的数据(是一个字典)
[[NSNotificationCenter defaultCenter] postNotificationName:@"DarkModeChanged"object:niluserInfo:@{@"isDark": @(YES)}];
-
响应通知,处理所传来的值。执行相关的操作
- (void)handleDarkModeChange:(NSNotification *)notification {NSDictionary *info = notification.userInfo;BOOL isDark = [info[@"isDark"] boolValue];// 根据是否是暗黑模式,更新界面self.view.backgroundColor = isDark ? [UIColor blackColor] : [UIColor whiteColor]; }
-
移除监听(可选)
- (void)dealloc {[[NSNotificationCenter defaultCenter] removeObserver:self]; }
防止内存泄漏,当视图销毁时移除监听,不然系统还会给已经释放的对象发消息,导致崩溃
Block传值
Block传值的用途与协议传值有点相似,主要都是用于从后一个控制器向前一个控制器传值
Block 传值是通过在一个控制器中定义一个 Block(类似函数),另一个控制器在跳转前将 Block 实现赋值,最终在需要的时候回调它,从而实现传值。
-
在后一个控制器声明一个Block属性(发出方)
// BViewController.h@interface BViewController : UIViewController@property (nonatomic, copy) void (^dataBlock)(NSString *data);@end
-
在前一个视图控制器设置Block的实现(接收方)
// AViewController.mBViewController *bVC = [[BViewController alloc] init]; bVC.dataBlock = ^(NSString *data) {NSLog(@"收到回传数据:%@", data); }; [self.navigationController pushViewController:bVC animated:YES];
-
在后一个视图控制器需要时调用Block(回调传值)
// BViewController.mif (self.dataBlock) {self.dataBlock(@"这是B传给A的值"); } [self.navigationController popViewControllerAnimated:YES];
Block传值的方法更简洁,更适合用于一次性回调的方式
单例(Singleton)
单例传值是一种更为高级的数据传递方式,适用于在多个界面之间传递数据。通过创建一个全局唯一的共享对象(单例类)来实现多个界面共享和访问同一个数据的方式。
主要适用于多个界面中进行数据的共享,而无需在每个界面中进行传递
-
创建一个单例类(数据中心)
// AppManager.h @interface AppManager : NSObject@property (nonatomic, strong) NSString *username; // 可传其他类型,如 BOOL isDarkMode+ (instancetype)sharedManager;@end
// AppManager.m @implementation AppManager+ (instancetype)sharedManager {static AppManager *manager = nil;static dispatch_once_t onceToken;dispatch_once(&onceToken, ^{manager = [[AppManager alloc] init];});return manager; }@end
这是一个全局对象,每次返回的都是同一个实例,可以放任何想共享的数据
-
在一个界面中设置数据
[AppManager sharedManager].username = @"小明";
在任何地方设置值,其他页面都能访问
-
在其他界面读取数据
NSString *name = [AppManager sharedManager].username; NSLog(@"读取到用户名:%@", name);
-
在整个运行周期存在,除非app关闭或者手动删除
[AppManager sharedManager].username = nil;
总结
多界面传值是UI中相当重要且常见的一个知识点,要根据具体情况进行方法的选择,有时甚至需要结合起来使用,比如通知与单例结合起来使用等 ,多加使用,才能更熟练