在iOS开发过程中,页面跳转时在页面之间进行数据传递是很常见的事情,我们称这个过程为页面传值。页面跳转过程中,从主页面跳转到子页面的数据传递称之为正向传值;反之,从子页面返回主页面时的数据传递称之为反向传值。
目前我所了解和掌握的传值方式有:
为了实现页面之间传值,我们需要准备两个页面,代码结构如下图所示。其中,KLMainViewController为主主页面,KLSubViewController为子页面,页面之间的跳转使用UINavigationController来实现。每个页面中都有一个文本编辑框,我们需要将其中一个页面文本框中的内容传递到另一个页面中。
1 #import "KLMainViewController.h" 2 #import "KLSubViewController.h" 3 4 @interface KLMainViewController () 5 6 @property (strong, nonatomic) UITextField *textField; 7 @property (strong, nonatomic) UIButton *button; 8 9 @end 10 11 @implementation KLMainViewController 12 13 - (void)viewDidLoad { 14 [super viewDidLoad]; 15 self.title = @"主界面"; 16 17 _textField = [[UITextField alloc] init]; 18 _textField.textColor = [UIColor redColor]; 19 _textField.textAlignment = NSTextAlignmentCenter; 20 _textField.backgroundColor = kBgColor; 21 _textField.text = @"主界面的label信息"; 22 [self.view addSubview:_textField]; 23 WEAKSELF 24 [_textField mas_makeConstraints:^(MASConstraintMaker *make) { 25 make.center.mas_equalTo(weakSelf.view).mas_offset(0.0f); 26 make.left.mas_equalTo(weakSelf.view).mas_offset(15.0f); 27 make.right.mas_equalTo(weakSelf.view).mas_offset(-15.0f); 28 }]; 29 30 _button = [UIButton buttonWithType:UIButtonTypeCustom]; 31 [_button setTitle:@"跳转到子界面" forState:UIControlStateNormal]; 32 [_button setTitleColor:[UIColor blueColor] forState:UIControlStateNormal]; 33 [_button addTarget:self action:@selector(btnClicked:) forControlEvents:UIControlEventTouchUpInside]; 34 [self.view addSubview:_button]; 35 [_button mas_makeConstraints:^(MASConstraintMaker *make) { 36 make.centerX.mas_equalTo(weakSelf.view).mas_offset(0.0f); 37 make.top.mas_equalTo(weakSelf.textField.mas_bottom).mas_offset(40.0f); 38 }]; 39 40 } 41 42 - (void) btnClicked:(UIButton *)btn { 43 KLSubViewController *subVC = [[KLSubViewController alloc] init]; 44 [self.navigationController pushViewController:subVC animated:YES]; 45 } 46 47 @endKLMainViewController.m
1 //KLSubViewController.h 2 #import <UIKit/UIKit.h> 3 4 NS_ASSUME_NONNULL_BEGIN 5 6 @interface KLSubViewController : UIViewController 7 8 @property (strong, nonatomic) UITextField *textField; 9 @property (strong, nonatomic) UIButton *button; 10 11 @property (strong, nonatomic) NSString *content; 12 13 @end 14 15 NS_ASSUME_NONNULL_END 16 17 //KLSubViewController.m 18 #import "KLSubViewController.h" 19 20 @interface KLSubViewController () 21 22 @end 23 24 @implementation KLSubViewController 25 26 - (void)viewDidLoad { 27 [super viewDidLoad]; 28 self.view.backgroundColor = [UIColor whiteColor]; 29 self.title = @"子界面"; 30 31 _textField = [[UITextField alloc] init]; 32 _textField.textColor = [UIColor redColor]; 33 _textField.textAlignment = NSTextAlignmentCenter; 34 _textField.backgroundColor = kBgColor; 35 _textField.text = @"子界面的label信息"; 36 [self.view addSubview:_textField]; 37 WEAKSELF 38 [_textField mas_makeConstraints:^(MASConstraintMaker *make) { 39 make.center.mas_equalTo(weakSelf.view).mas_offset(0.0f); 40 make.left.mas_equalTo(weakSelf.view).mas_offset(15.0f); 41 make.right.mas_equalTo(weakSelf.view).mas_offset(-15.0f); 42 }]; 43 44 _button = [UIButton buttonWithType:UIButtonTypeCustom]; 45 [_button setTitle:@"返回主界面" forState:UIControlStateNormal]; 46 [_button setTitleColor:[UIColor blueColor] forState:UIControlStateNormal]; 47 [_button addTarget:self action:@selector(btnClicked:) forControlEvents:UIControlEventTouchUpInside]; 48 [self.view addSubview:_button]; 49 [_button mas_makeConstraints:^(MASConstraintMaker *make) { 50 make.centerX.mas_equalTo(weakSelf.view).mas_offset(0.0f); 51 make.top.mas_equalTo(weakSelf.textField.mas_bottom).mas_offset(40.0f); 52 }]; 53 } 54 55 - (void) btnClicked:(UIButton *)btn { 56 57 [self.navigationController popViewControllerAnimated:YES]; 58 } 59 60 @endKLSubViewController
方法描述:在从当前页面跳转到下主页面之前,提前创建下主页面,通过赋值的方式将当前页面的数据赋予下主页面的属性。
适用场景:当从主页面push到子页面时,子页面需要使用到主页面的数据,我们需要使用到正向传值。
传递方式:正向传值。
使用步骤:
//子页面KLSubViewController.h的属性定义 @interface KLSubViewController : UIViewController @property (strong, nonatomic) UITextField *textField; @property (strong, nonatomic) UIButton *button; @property (strong, nonatomic) NSString *content;//属性接收数据 @end
//主界面跳转时将数据赋值给对应的属性 @interface KLMainViewController () @property (strong, nonatomic) UITextField *textField; @property (strong, nonatomic) UIButton *button; @end @implementation KLMainViewController - (void)viewDidLoad { [super viewDidLoad]; self.title = @"主界面"; //布局代码省略 ...... } //跳转 - (void) btnClicked:(UIButton *)btn { KLSubViewController *subVC = [[KLSubViewController alloc] init]; subVC.content = @"来自主界面的数据"; // subVC.textField.text = @"来自主界面的数据"; //这样传递是有问题的,因为子页面中的textfield是在viewDidLoad中进行初始化和布局的,在这时候textfield还没有初始化,为nil,所以赋值是失效的 [self.navigationController pushViewController:subVC animated:YES]; } @end
方法描述:首先在子页面的头文件中添加一个代理(协议)的定义,定义一个传递数据的方法,并且在子页面的类中添加一个代理属性;然后,在子页面返回主页面之前调用代理中定义的数据传递方法(方法参数就是要传递的数据);最后,在主页面中遵从该代理,并实现代理中定义的方法,在方法的实现代码中将参数传递给主页面的属性。
适用场景:已经通过push的方式进入到子页面,在从子页面返回主页面的时候(子页面会释放掉内存),需要在主页面中使用子页面中的数据,这是就可以利用代理反向传值。
传递方式:反向传值。
使用步骤:
//子页面的.h文件,定义代理以及代理属性 // 声明代理 @protocol BToADelegate <NSObject> // 代理方法 - (void)transferString:(NSString *)string; @end @interface KLSubViewController : UIViewController @property (strong, nonatomic) UITextField *textField; @property (strong, nonatomic) UIButton *button; @property (nonatomic, weak) id<BToADelegate> delegate;//代理属性 @end
//子页面返回时调用代理方法 - (void) btnClicked:(UIButton *)btn { //如果当前的代理存在,并且实现了代理方法,则调用代理方法进行传递数据 if (self.delegate && [self.delegate respondsToSelector:@selector(transferString:)]) { [self.delegate transferString:@"子页面回传的数据"]; } [self.navigationController popViewControllerAnimated:YES]; }
//要实现BToADelegate @interface KLMainViewController () <BToADelegate> @property (strong, nonatomic) UITextField *textField; @property (strong, nonatomic) UIButton *button; @end @implementation KLMainViewController - (void)viewDidLoad { [super viewDidLoad]; self.title = @"主界面"; //布局代码省略 ... } - (void) btnClicked:(UIButton *)btn { KLSubViewController *subVC = [[KLSubViewController alloc] init]; subVC.delegate = self; //申明子页面的代理是主页面自身self [self.navigationController pushViewController:subVC animated:YES]; } #pragma mark BToADelegate 代理方法,子页面调用的时候会回调该方法 - (void)transferString:(NSString *)string { self.textField.text = string; } @end
方法描述:在子页面中添加一个块语句属性,在子页面返回主页面之前调用该块语句。在主页面跳转子页面之前,设置子页面中的块语句属性将要执行的动作(回调函数)。这样,在子页面返回主页面时就会调用该回调函数来传递数据。
适用场景:已经通过push的方式进入到子页面,在从子页面返回主页面的时候(子页面会释放掉内存),需要在主页面中使用子页面中的数据,这是就可以利用代理反向传值。
传递方式:反向传递。
使用步骤:整个步骤和代理差不多
//定义block的类型 typedef void (^TransDataBlock)(NSString *content); @interface KLSubViewController : UIViewController @property (strong, nonatomic) UITextField *textField; @property (strong, nonatomic) UIButton *button; @property (copy, nonatomic) TransDataBlock transDataBlock;//定义一个block属性,用于回传数据 @end
#import "KLSubViewController.h" @interface KLSubViewController () @end @implementation KLSubViewController - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor whiteColor]; self.title = @"子界面"; //布局代码省略 ...... } - (void) btnClicked:(UIButton *)btn { //如果回传block存在 则调用该block进行回传数据 if (self.transDataBlock) { self.transDataBlock(@"子页面回传的数据"); } [self.navigationController popViewControllerAnimated:YES]; } @end
#import "KLMainViewController.h" #import "KLSubViewController.h" @interface KLMainViewController () @property (strong, nonatomic) UITextField *textField; @property (strong, nonatomic) UIButton *button; @end @implementation KLMainViewController - (void)viewDidLoad { [super viewDidLoad]; self.title = @"主界面"; //布局代码省略 ...... } - (void) btnClicked:(UIButton *)btn { KLSubViewController *subVC = [[KLSubViewController alloc] init]; //通过子页面的block回传拿到数据后进行处理,赋值给当前页面的textfield subVC.transDataBlock = ^(NSString *content) { self.textField.text = content; }; [self.navigationController pushViewController:subVC animated:YES]; } @end
方法描述:在通知接收方需要注册通知,并指定接收到通知后进行的操作;而在通知发送方则在需要传递数据时发送通知就OK了。通知的操作都是通过NSNotificationCenter来完成的。
但是要注意的两点是:
注册的接收通知的名称必须和发送通知的名称保持一致才能接收到,否则无法接收到发出的通知
适用场景:
传递方式:正向传递(很少这样用)、反向传递(更常用)。
使用步骤:
@interface KLSubViewController () @end @implementation KLSubViewController - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor whiteColor]; self.title = @"子界面"; //布局代码省略 ....... } - (void) btnClicked:(UIButton *)btn { //发送通知回传数据,回传的数据格式自定义,这里定义为dictionary类型 [[NSNotificationCenter defaultCenter] postNotificationName:@"TransDataNoti" object:nil userInfo:@{@"content":@"子页面回传的数据"}]; [self.navigationController popViewControllerAnimated:YES]; }
@interface KLMainViewController () @property (strong, nonatomic) UITextField *textField; @property (strong, nonatomic) UIButton *button; @end @implementation KLMainViewController - (void)dealloc { //移除所有通知 [[NSNotificationCenter defaultCenter] removeObserver:self]; // 移除某个 // [[NSNotificationCenter defaultCenter] removeObserver:self name:@"TransDataNoti" object:nil]; } - (void)viewDidLoad { [super viewDidLoad]; self.title = @"主界面"; //布局代码省略 ...... //注册通知,用于接收通知,接收通知的名称必须和发送通知的名称保持一致才能接收到,否则无法接收到发出的通知 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(notiReceived:) name:@"TransDataNoti" object:nil]; } //接收通知,解析内容进行处理 - (void)notiReceived:(NSNotification *)sender { self.textField.text = sender.userInfo[@"content"]; } - (void) btnClicked:(UIButton *)btn { KLSubViewController *subVC = [[KLSubViewController alloc] init]; [self.navigationController pushViewController:subVC animated:YES]; } @end
@interface KLMainViewController () @property (strong, nonatomic) UITextField *textField; @property (strong, nonatomic) UIButton *button; @end @implementation KLMainViewController - (void)viewDidLoad { [super viewDidLoad]; self.title = @"主界面"; //布局代码省略 ...... } - (void) btnClicked:(UIButton *)btn { KLSubViewController *subVC = [[KLSubViewController alloc] init]; //发送通知回传数据,回传的数据格式自定义,这里定义为dictionary类型 [[NSNotificationCenter defaultCenter] postNotificationName:@"TransDataNoti" object:nil userInfo:@{@"content":@"主页面传递的数据"}]; [self.navigationController pushViewController:subVC animated:YES]; } @end
@interface KLSubViewController () @end @implementation KLSubViewController - (void)dealloc { //移除所有通知 [[NSNotificationCenter defaultCenter] removeObserver:self]; // 移除某个 // [[NSNotificationCenter defaultCenter] removeObserver:self name:@"TransDataNoti" object:nil]; } - (instancetype)init { self = [super init]; //初始化代码省略 ...... //注册通知,用于接收通知,接收通知的名称必须和发送通知的名称保持一致才能接收到,否则无法接收到发出的通知 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(notiReceived:) name:@"TransDataNoti" object:nil]; return self; } - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor whiteColor]; self.title = @"子界面"; } //接收通知,解析内容进行处理 - (void)notiReceived:(NSNotification *)sender { self.textField.text = sender.userInfo[@"content"]; } - (void) btnClicked:(UIButton *)btn { [self.navigationController popViewControllerAnimated:YES]; } @end
方法描述:NSUserDefaults传值是将所要传的值写在沙盒目录里面,需要获取值的时候直接访问沙盒,获取这个值就可以了,这种传值方法一般用在需要将数据本地存储的时候,比如:用户名之类,当用户下次登录或者使用app的时候,可以直接从本地读取。
适用场景:任何需要数据传递的场景都适用,但是传递数据的类型仅限于基本数据类型,不能用于自定义的对象类型。
传递方式:正向传值、反向传值。
使用步骤:
- (void) btnClicked:(UIButton *)btn { /* setObject:后面写的就是所需要传递的值 forKey:要具有唯一性、一致性; 唯一性是指:当代码中用到多个NSUserDefaults方法时,要保证不同的key不一样,否则就是覆盖值 一致性:这里传递一个值,当需要用到的时候,要用valueForkey的方法,这个key和传值时候写的key要一样,写错了就找不到值了。 */ [[NSUserDefaults standardUserDefaults] setObject:@"NSUserDefaults传值" forKey:@"NSUserDefaults"]; [[NSUserDefaults standardUserDefaults] synchronize]; [self.navigationController popViewControllerAnimated:YES]; }
_label.text = [[NSUserDefaults standardUserDefaults] valueForKey:@"NSUserDefaults"];
方法描述:单例传值的性质和NSUserDefaults传值的性质类似,只是单例传值是将数据保存在单例对象中,需要的时候同样从单例对象中去获取数据使用就ok。
适用场景:任何需要数据传递的场景都适用,传递的数据可以是任何类型的数据。
<
参与评论
手机查看
返回顶部