什么是页面间传值:
几种常见的页面传值方式
#import
#import "NextViewController.h" // 引入页面2的头文件
@interface ViewController : UIViewController
@end
因为要跳转到页面2,因此需要引入页面2的头文件
#import "ViewController.h"
@interface ViewController ()
@property(nonatomic,strong) UILabel *label; // 用于显示
@property(nonatomic,strong) UIButton *btn; // 用于跳转
@end
@implementation ViewController
- (UILabel *)label{
if(_label == nil){
_label = [[UILabel alloc]initWithFrame:CGRectMake(100, 100, 200, 40)];
_label.backgroundColor = [UIColor blackColor];
_label.textColor = [UIColor whiteColor];
_label.font = [UIFont systemFontOfSize:20];
}
return _label;
}
- (UIButton *)btn{
if(_btn == nil){
_btn = [[UIButton alloc]initWithFrame:CGRectMake(100, 300, 200, 40)];
_btn.backgroundColor = [UIColor redColor];
[_btn setTitle:@"跳转至页面2" forState:UIControlStateNormal];
[_btn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[_btn addTarget:self action:@selector(btnClick) forControlEvents:UIControlEventTouchUpInside];
}
return _btn;
}
// btn点击事件,跳转至页面2
- (void) btnClick{
NextViewController *nextVC = [[NextViewController alloc] init];
[self presentViewController:nextVC animated:YES completion:nil];
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self.view addSubview:self.label];
[self.view addSubview:self.btn];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
#import "NextViewController.h"
@interface NextViewController ()
@property(nonatomic,strong) UITextField *textField;
@property(nonatomic,strong) UIButton *btn;
@end
@implementation NextViewController
- (UITextField *)textField{
if(!_textField){
_textField = [[UITextField alloc]initWithFrame:CGRectMake(100, 100, 200, 40)];
_textField.textColor = [UIColor blackColor];
_textField.font = [UIFont systemFontOfSize:20];
_textField.borderStyle = UITextBorderStyleLine;
}
return _textField;
}
- (UIButton *)btn{
if(!_btn){
_btn = [[UIButton alloc]initWithFrame:CGRectMake(100, 300, 200, 40)];
_btn.backgroundColor = [UIColor redColor];
[_btn setTitle:@"跳转回页面1" forState:UIControlStateNormal];
[_btn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[_btn addTarget:self action:@selector(btnClick) forControlEvents:UIControlEventTouchUpInside];
}
return _btn;
}
- (void)btnClick{
[self dismissViewControllerAnimated:YES completion:nil];
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.view.backgroundColor = [UIColor whiteColor];
[self.view addSubview:self.textField];
[self.view addSubview:self.btn];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
@end
从页面1向页面2跳转的时候为页面2的属性赋值
属性传值是非常有效的正向传值方式
在页面2中创建属性NSString *str
#import
@interface NextViewController : UIViewController
@property(nonatomic,strong) NSString *str;
@end
在页面2中创建属性NSString *str
// btn点击事件,跳转至页面2
- (void) btnClick{
NextViewController *nextVC = [[NextViewController alloc] init];
// 属性传值 - 传递
nextVC.str = @"属性传值";
[self presentViewController:nextVC animated:YES completion:nil];
}
- (UITextField *)textField{
if(!_textField){
_textField = [[UITextField alloc]initWithFrame:CGRectMake(100, 100, 200, 40)];
_textField.textColor = [UIColor blackColor];
_textField.font = [UIFont systemFontOfSize:20];
_textField.borderStyle = UITextBorderStyleLine;
// 属性传值 - 接收并显示
_textField.text = self.str;
}
return _textField;
}
两个页面通过单例对象进行传值
#import
@interface DefaultInstance : NSObject
+ (instancetype)sharedInstance;
@property(nonatomic,strong) NSString *str;
@end
声明了一个属性用于传值
#import "DefaultInstance.h"
@implementation DefaultInstance
// 通过类方法创建单例对象
+ (instancetype)sharedInstance{
static DefaultInstance *sharedVC = nil;
if(sharedVC == nil){
sharedVC = [DefaultInstance new];
}
return sharedVC;
}
@end
实现了单例方法
#import
#import "NextViewController.h"
#import "DefaultInstance.h"
@interface ViewController : UIViewController
@end
引入单例对象,因为需要通过单例对象进行传值
// btn点击事件,跳转至页面2
- (void) btnClick{
NextViewController *nextVC = [[NextViewController alloc] init];
// 单例传值 - 传递
[DefaultInstance sharedInstance].str = @"单例传值";
[self presentViewController:nextVC animated:YES completion:nil];
}
在页面跳转的地方通过单例对象接收传值
#import
#import "DefaultInstance.h"
@interface NextViewController : UIViewController
@end
引入单例对象,因为需要通过单例对象传值
- (UITextField *)textField{
if(!_textField){
_textField = [[UITextField alloc]initWithFrame:CGRectMake(100, 100, 200, 40)];
_textField.textColor = [UIColor blackColor];
_textField.font = [UIFont systemFontOfSize:20];
_textField.borderStyle = UITextBorderStyleLine;
// 单例传值 - 接收并显示
_textField.text = [DefaultInstance sharedInstance].str;
}
return _textField;
}
接收并显示单例对象传值
上面实现了正向单例传值,但单例传值还可以逆向传值,即页面2向页面1传值
- (void)btnClick{
// 单例逆向传值 - 传递
[DefaultInstance sharedInstance].str = _textField.text;
[self dismissViewControllerAnimated:YES completion:nil];
}
- (void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
// 单例逆向传值 - 接收并显示
_label.text = [DefaultInstance sharedInstance].str;
}
在页面2中通过单例逆向传递textField.text的值,在页面1的viewWillAppear中通过单例逆向接收并显示传递的值
单例传值的应用范围很广泛,不仅可以页面间正向和逆向传值,还可以跨页面传值
通过NSUserDefaults读写数据的方式,通过沙盒文件进行传值
// btn点击事件,跳转至页面2
- (void) btnClick{
NextViewController *nextVC = [[NextViewController alloc] init];
// NSUserDefaults传值 - 正向传递数据到沙盒文件中
[[NSUserDefaults standardUserDefaults]setObject:@"NSUserDefaults传值" forKey:@"NSUserDefaults"];
[[NSUserDefaults standardUserDefaults]synchronize];
[self presentViewController:nextVC animated:YES completion:nil];
}
用字典的方式向沙盒文件中传值并刷新沙盒文件
- (UITextField *)textField{
if(!_textField){
_textField = [[UITextField alloc]initWithFrame:CGRectMake(100, 100, 200, 40)];
_textField.textColor = [UIColor blackColor];
_textField.font = [UIFont systemFontOfSize:20];
_textField.borderStyle = UITextBorderStyleLine;
// NSUserDefaults传值 - 从沙盒文件中读取并显示
_textField.text = [[NSUserDefaults standardUserDefaults] objectForKey:@"NSUserDefaults"];
}
return _textField;
}
用字典的方式读取沙盒文件中的传值并显示
NextViewController.m
- (void)btnClick{
// NSUserDefaults逆向传值
[[NSUserDefaults standardUserDefaults] setObject:_textField.text forKey:@"NSUserDefaults - re"];
[[NSUserDefaults standardUserDefaults]synchronize];
[self dismissViewControllerAnimated:YES completion:nil];
}
返回页面时,通过字典方式向NSUserDefaults沙盒文件中写入值,并同步沙盒文件
ViewController.m
- (void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
// NSUserDefaults反向传值 - 接收并显示数据
_label.text = [[NSUserDefaults standardUserDefaults] objectForKey:@"NSUserDefaults - re"];
}
在ViewController将要显示的时候,通过字典方式从NSUserDefault沙盒文件取出并显示传值
当然NSUserDefaults也可以跨文件传值
代理传值是IOS中最重要并且用的最多的传值方式
委托方和代理方共同遵守一份协议就可以通讯了,
委托方持有协议调用协议方法进行传值,
代理方遵守协议实现协议方法就可以接收委托方传过来的值
代理传值主要用于反向传值
#import
// 委托方创建一个协议
@protocol passValueDelegate <NSObject>
// 协议定义一个传值的方法
- (void)passValue:(NSString *)str;
@end
@interface NextViewController : UIViewController
@property(nonatomic,strong) NSString *str;
// 定义一个持有协议的id指针,为防止循环引用一般使用weak来定义指针
@property(weak) iddelegate;
@end
#import "ViewController.h"
@interface ViewController ()<passValueDelegate> // 代理方遵守协议
@property(nonatomic,strong) UILabel *label;
@property(nonatomic,strong) UIButton *btn;
@end
@implementation ViewController
- (UILabel *)label{
if(_label == nil){
_label = [[UILabel alloc]initWithFrame:CGRectMake(100, 100, 200, 40)];
_label.backgroundColor = [UIColor blackColor];
_label.textColor = [UIColor whiteColor];
_label.font = [UIFont systemFontOfSize:20];
}
return _label;
}
- (UIButton *)btn{
if(_btn == nil){
_btn = [[UIButton alloc]initWithFrame:CGRectMake(100, 300, 200, 40)];
_btn.backgroundColor = [UIColor redColor];
[_btn setTitle:@"跳转至页面2" forState:UIControlStateNormal];
[_btn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[_btn addTarget:self action:@selector(btnClick) forControlEvents:UIControlEventTouchUpInside];
}
return _btn;
}
- (void) btnClick{
NextViewController *nextVC = [[NextViewController alloc] init];
// 代理传值 - 设置代理关系
nextVC.delegate = self;
[self presentViewController:nextVC animated:YES completion:nil];
}
// 代理传值 -- 代理方实现协议方法 -- 接收来自页面2的值
- (void)passValue:(NSString *)str{ //
self.label.text = str;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self.view addSubview:self.label];
[self.view addSubview:self.btn];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
block是目前苹果最推荐和最流行的传值方式,它可以做代理传值一样的事情,但比代理传值写法更简单更容易理解,它省去了定义协议设置代理的过程
页面1跳转到页面2,页面2回调block传值,页面1只需要实现block接收数据就可以了
block传值也主要用于反向页面传值
#import
@interface NextViewController : UIViewController
// 定义一个block进行页面反向传值,为防止页面循环引用block一般定义为copy属性
@property(copy) void (^block)(NSString *);
@end
页面2定义block
- (void)btnClick{
// block传值 - 反向传值
self.block(self.textField.text);
[self dismissViewControllerAnimated:YES completion:nil];
}
在页面2回调到页面1方法中回调block
// btn点击事件,跳转至页面2
- (void) btnClick{
NextViewController *nextVC = [[NextViewController alloc] init];
// block传值 - 实现block - 接收来自页面2的值
nextVC.block = ^(NSString *str){
self.label.text = str;
};
[self presentViewController:nextVC animated:YES completion:nil];
}
在页面1跳转到页面2的方法中实现block
接收方在通知中心进行注册,发送方将通知发送到通知中心,通知中心拿到数据再回调给接收方
可以进行跨页面传值,是一种多对多的传值方式
模拟页面2发送通知到页面1
页面1作为接收方
// btn点击事件,跳转至页面2
- (void) btnClick{
NextViewController *nextVC = [[NextViewController alloc] init];
// 通知传值 - 添加监听 - 等待页面2的传值,参数object表示通知要发给谁,nil的话就是群发
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(notHandler:) name:@"notify" object:nil];
[self presentViewController:nextVC animated:YES completion:nil];
}
在跳转到页面2之前定义定义一个观察者
- (void)btnClick{
// 通知传值 - 发送通知
[[NSNotificationCenter defaultCenter] postNotificationName:@"notify" object:nil userInfo:@{@"not":self.textField.text}];
[self dismissViewControllerAnimated:YES completion:nil];
}
在回调到页面1之前,发送方将通知发送到通知中心
// 接收到通知之后的处理 - 参数1就是通知
- (void)notHandler:(NSNotification *)not{
self.label.text = not.userInfo[@"not"];
}
通知中心将拿到数据后将通知回调给接收方