iOS五种页面传值方式

来源:互联网 发布:php空间试用 编辑:程序博客网 时间:2024/06/10 18:46

页面传值是很常用的一个东西,这里介绍比较常用的五种:属性传值,block传值,代理传值,单例传值,通知传值。
(一)属性传值 
实践方案:第二个界面中的lable显示第一个界面textField中输入的文本
实践步骤:
首先我们建立一个RootViewControllers和一个DetailViewControllers(detail页面的label显示root页面textField输入的内容),在DetailViewControllers中声明一个textString属性,用于接收传过来的字符串:

//DetailViewControllerOne.h#import <UIKit/UIKit.h>@interface DetailViewControllerOne : UIViewController@property (nonatomic , strong) NSString *textString;@end

同时创建一个Lable用来显示传过的字符串

//DetailViewControllerOne.m#import "DetailViewControllerOne.h"@interface DetailViewControllerOne ()@end@implementation DetailViewControllerOne- (void)viewDidLoad {    [super viewDidLoad];    UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(20, 100, CGRectGetWidth(self.view.bounds)-40, 30)];    label.backgroundColor = [UIColor orangeColor];    label.font = [UIFont systemFontOfSize:20];    label.numberOfLines = 0;    label.text = self.textString;  //使用传递过来的值    [self.view addSubview:label];    self.view.backgroundColor = [UIColor greenColor];}

在RootViewControllers上引入DetailViewControllers同时声明一个textField属性用来输入字符串

//RootViewControllers.m#import "RootViewControllerOne.h"#import "DetailViewControllerOne.h"@interface RootViewControllerOne ()@property(nonatomic , strong) UITextField *textField;@end@implementation RootViewControllerOne- (void)viewDidLoad {    [super viewDidLoad];    self.title = @"属性传值";    self.view.backgroundColor = [UIColor whiteColor];    [self.view addSubview:self.textField];        // 创建一个轻拍手势,当点击屏幕任何一个地方,就取消键盘的第一响应,隐藏键盘    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)];    [self.view addGestureRecognizer:tap];        UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];    button.frame = CGRectMake(20, 200, CGRectGetWidth(self.view.bounds)-40, 40);    [button setTitle:@"下一页" forState:UIControlStateNormal];    button.titleLabel.font = [UIFont systemFontOfSize:20];    button.backgroundColor = [UIColor greenColor];        [button addTarget:self action:@selector(clickAction:) forControlEvents:UIControlEventTouchUpInside];    [self.view addSubview:button];}-(UITextField *)textField {    if (!_textField) {        _textField = [[UITextField alloc] initWithFrame:CGRectMake(20, 100, CGRectGetWidth(self.view.bounds)-40, 40)];        _textField.backgroundColor = [UIColor greenColor];        _textField.placeholder = @"请输入内容";            }    return _textField;}//放弃作为第一响应者- (void)handleTap:(id)sender {    [_textField resignFirstResponder];}//页面跳转-(void)clickAction:(id)sender {    DetailViewControllerOne *dVC = [[DetailViewControllerOne alloc] init];    dVC.textString = self.textField.text;  //利用detail的textString属性保存textField输入的内容    [self.navigationController pushViewController:dVC animated:NO];}

小结:属性传值的核心就是在一个页面通过使用另一个页面的属性,利用这个属性来保存需要传递的信息,从而达到在另一个页面能使用前一个页面传递过来的信息。


(二)Block传值
实践方案:当第二个页面返回第一个页面时,在第一个页面中的lable显示第二个界面textField中输入的文本
实践步骤:
首先我们建立一个RootViewControllers和一个DetailViewControllers(root页面的label显示detail页面textField输入的内容),在RootViewControllers里面新建一个用于显示的Label

//RootViewControllers.h#import <UIKit/UIKit.h>@interface RootViewControllerTwo : UIViewController@property (nonatomic,retain) UILabel *label;@end

在DetailViewControllers里面新建一个用于传值的Block,一个Block方法和一个用于输入内容的textField

//DetailViewControllers.h#import <UIKit/UIKit.h>typedef void (^ReturnTextBlock)(NSString *showText);//重新定义了一个名字@interface DetailViewControllerTwo :UIViewController@property (nonatomic,retain) UITextField *tf;@property (nonatomic,copy) ReturnTextBlock returnTextBlock;//定义的一个Block属性- (void)returnText:(ReturnTextBlock)block;@end

将传递过来的block赋值给自己的属性block,然后找一个时机给block传递数据

//DetailViewControllers.m#import "DetailViewControllerTwo.h"#import "RootViewControllerTwo.h"@implementation DetailViewControllerTwo- (void)viewDidLoad {        [super viewDidLoad];    self.view.backgroundColor = [UIColor whiteColor];        //定义一个输入框 将文字传给第一个界面,并且显示在前一个页面的UILabel上    self.tf = [[UITextField alloc]initWithFrame:CGRectMake(20,100,CGRectGetWidth(self.view.bounds) - 40 , 40)];    self.tf.tintColor = [UIColor orangeColor];     self.tf.backgroundColor = [UIColor greenColor];    self.tf.placeholder = @"请输入内容";        [self.view addSubview:self.tf];        //定义一个按钮    UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];    button.frame = CGRectMake(20,300,CGRectGetWidth(self.view.bounds) - 40 , 40);    button.backgroundColor = [UIColor redColor];    [button setTitle:@"返回" forState:UIControlStateNormal];    [button addTarget:self action:@selector(clickAction:) forControlEvents:UIControlEventTouchUpInside];        [self.view addSubview:button];}/*在第一个界面传进来一个Block语句块的函数,把传进来的Block语句块保存到本类的实例变  量returnTextBlock(.h中定义的属性)中,然后寻找一个时机调用*/-(void)returnText:(ReturnTextBlock)block{    self.returnTextBlock = block;}//而这个时机就是当视图将要消失的时候,需要重写:-(void)viewWillDisappear:(BOOL)animated{    if (self.returnTextBlock !=nil) {        self.returnTextBlock(self.tf.text);    }}//此处的点击事件也会触发视图消失,所以同样会走上面的viewWillDisappear方法-(void)clickAction:(id)sender {    [self.navigationController popViewControllerAnimated:NO];}@end

读取block传递过来的数据,并显示在label中

//RootViewControllers.m#import "RootViewControllerTwo.h"#import "DetailViewControllerTwo.h"@interface RootViewControllerTwo ()@end@implementation RootViewControllerTwo- (void)viewDidLoad {    [super viewDidLoad];    self.title = @"Block传值";    self.view.backgroundColor = [UIColor whiteColor];        //定义一个按钮    UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];    button.frame = CGRectMake(20,300,CGRectGetWidth(self.view.bounds) - 40 , 40);    button.backgroundColor = [UIColor blueColor];    [button setTitle:@"下一页" forState:UIControlStateNormal];    [button addTarget:self action:@selector(clickAction:) forControlEvents:UIControlEventTouchUpInside];        [self.view addSubview:button];        //定义一个显示控件    self.label = [[UILabel alloc] initWithFrame:CGRectMake(20,100, CGRectGetWidth(self.view.bounds) - 40 , 40)];    self.label.backgroundColor = [UIColor purpleColor];    self.label.text = @"用于显示从后面页面返回的数据";//为了显示第二个视图控制器传过来的字符串    self.label.textColor = [UIColor whiteColor];    [self.view addSubview:self.label];}-(void)clickAction:(id)sender{        DetailViewControllerTwo * dVC =[[DetailViewControllerTwo alloc] init];//相对应的将其实例化,否则找不到相应的属性        //回调方法将输入框中的数据传输过来    [dVC returnText:^(NSString *showText) {        self.label.text = showText;    }];        [self.navigationController pushViewController:dVC animated:YES];}

小结:其实block传值还是有点类似于属性传值,但是他是将值保存在代码块中,通过关联传递过来的代码块(页面一)与自己的属性代码块(页面二),以及使用代码块传值(页面二),回到页面一中,页面一回调代码块,以获取代码块传递过来的值。


(三)代理传值 
实践方案:第一个界面中的lable显示第二个界面textField中输入的文本
实践步骤:
首先我们建立一个RootViewControllers和一个DetailViewControllers(root页面的label显示detail页面textField输入的内容),首先我们先声明一个代理以及代理需要实现的方法

//DetailViewController.h#import <UIKit/UIKit.h>@class DetailViewControllerThree;@protocol PassingValueDeletegate <NSObject>@optional-(void)viewController:(DetailViewControllerThree *)viewController didPassingValueWithInfo:(id)info;@end@interface DetailViewControllerThree : UIViewController@property(nonatomic, assign) id<PassingValueDeletegate> delegate;//通过代理传值@end

在一个需要传值的时机,将需要传递的值保存到代理方法的参数中

//DetailViewController.m#import "DetailViewControllerThree.h"@interface DetailViewControllerThree ()@property (nonatomic, strong) UITextField *textField;@end@implementation DetailViewControllerThree- (void)viewDidLoad {    [super viewDidLoad];    // Do any additional setup after loading the view.    self.view.backgroundColor = [UIColor whiteColor];        UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];    button.frame = CGRectMake(20, 300, CGRectGetWidth(self.view.bounds)-40, 40);    [button setTitle:@"返回" forState:UIControlStateNormal];    button.backgroundColor = [UIColor blueColor];    [button addTarget:self action:@selector(clickAction:) forControlEvents:UIControlEventTouchUpInside];        [self.view addSubview:button];    [self.view addSubview:self.textField];}- (void)didReceiveMemoryWarning {    [super didReceiveMemoryWarning];    // Dispose of any resources that can be recreated.}-(void)viewWillDisappear:(BOOL)animated {    [super viewWillDisappear:animated];    NSString *string;        if ([_textField.text length] == 0) {        string = @"用户未输入任何内容";    }else {        string = _textField.text;    }    //视图将要消失,通过代理传值    //首次判断代理是否存在,并在代理能够响应代理方法时才执行代理方法    if (self.delegate && [self.delegate respondsToSelector:@selector(viewController:didPassingValueWithInfo:)]) {        [self.delegate viewController:self didPassingValueWithInfo:string];    }}-(UITextField *)textField {    if (!_textField) {        _textField = [[UITextField alloc] initWithFrame:CGRectMake(20, 100, CGRectGetWidth(self.view.bounds) - 40, 40)];    }    _textField.placeholder = @"请输入内容";    _textField.backgroundColor = [UIColor greenColor];    return _textField;}-(void)clickAction:(id)sender {    [self.navigationController popViewControllerAnimated:NO];}

声明RootViewController实现该代理,并实现该代理的方法,而该代理方法就包含着传递过来的值

//RootViewController.m#import "RootViewControllerThree.h"#import "DetailViewControllerThree.h"@interface RootViewControllerThree () <PassingValueDeletegate>@property (nonatomic, strong) UILabel *showLabel;@end@implementation RootViewControllerThree- (void)viewDidLoad {    [super viewDidLoad];    self.title = @"代理传值";    self.view.backgroundColor = [UIColor whiteColor];    [self.view addSubview:self.showLabel];    UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];    button.frame = CGRectMake(20, 300, CGRectGetWidth(self.view.bounds)-40, 40);    [button setTitle:@"下一页" forState:UIControlStateNormal];    button.titleLabel.font = [UIFont systemFontOfSize:20];    button.backgroundColor = [UIColor greenColor];        [button addTarget:self action:@selector(clickAction:) forControlEvents:UIControlEventTouchUpInside];    [self.view addSubview:button];}- (void)didReceiveMemoryWarning {    [super didReceiveMemoryWarning];    // Dispose of any resources that can be recreated.}- (UILabel *)showLabel {    if (!_showLabel) {        _showLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 200, CGRectGetWidth(self.view.bounds)-40, 40)];    }    _showLabel.text = @"用于显示后面页面传过来的值";    _showLabel.textColor = [UIColor whiteColor];    _showLabel.backgroundColor = [UIColor purpleColor];    return _showLabel;}-(void)clickAction:(id)sender {    DetailViewControllerThree *dVC = [[DetailViewControllerThree alloc] init];    dVC.delegate = self;        [self.navigationController pushViewController:dVC animated:NO];}-(void)viewController:(DetailViewControllerThree *)viewController didPassingValueWithInfo:(id)info {    _showLabel.text = info;  //代理方法传递过来的值}

小结:代理方法是用的比较多的,适用于任意界面之间传值,只需要声明实现代理方法,就可以获取传递过来的值


(四)单例传值 
实践方案:第一个界面中的lable显示第二个界面textField中输入的文本,同时第二个界面中的lable显示第一个界面textField中输入的文本,输入文本互相传递
实践步骤:新建一个单例

#import <Foundation/Foundation.h>@interface AppStatus : NSObject {    NSString *_contextStr;}@property(nonatomic,retain)NSString *contextStr;+(AppStatus *)shareInstance;@end#import "AppStatus.h"@implementation AppStatus@synthesize contextStr = _contextStr;static AppStatus *_instance = nil;+(AppStatus *)shareInstance{    if (_instance == nil)    {        _instance = [[super alloc]init];    }    return _instance;}-(id)init{    if (self = [super init])    {            }    return self;}@end
#import "RootViewControllerFour.h"#import "AppStatus.h"#import "DetailViewControllerFour.h"@interface RootViewControllerFour ()@property (nonatomic, strong) UILabel *label;@property (nonatomic, strong) UITextField *textField;@end@implementation RootViewControllerFour- (void)viewDidLoad {    [super viewDidLoad];    // Do any additional setup after loading the view.    self.view.backgroundColor = [UIColor whiteColor];    self.title = @"单例传值";        UIButton *btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];    btn.frame = CGRectMake(20, 300, CGRectGetWidth(self.view.bounds) -40, 40);    [btn setTitle:@"Push" forState:UIControlStateNormal];    btn.backgroundColor = [UIColor redColor];    [btn addTarget:self action:@selector(pushAction:) forControlEvents:UIControlEventTouchUpInside];    [self.view addSubview:btn];    [self.view addSubview:self.textField];    self.label.frame = CGRectMake(20, 100, CGRectGetWidth(self.view.bounds) -40, 40);        self.label.backgroundColor = [UIColor greenColor];    [self.view addSubview:self.label];}-(void)viewWillAppear:(BOOL)animated {    if ([AppStatus shareInstance].contextStr.length !=0) {        self.label.text = [AppStatus shareInstance].contextStr;    } else {        self.label.text = @"用于现实后面页面传递过来的值";    }}- (void)didReceiveMemoryWarning {    [super didReceiveMemoryWarning];    // Dispose of any resources that can be recreated.}-(UITextField *)textField {    if (!_textField) {        _textField = [[UITextField alloc] initWithFrame:CGRectMake(20, 200, CGRectGetWidth(self.view.bounds)-40, 40)];    }    _textField.placeholder = @"请输入内容";    _textField.backgroundColor = [UIColor purpleColor];    _textField.textColor = [UIColor whiteColor];    return _textField;}-(void)pushAction:(id)sender{//    _textField = (UITextField *)[self.view viewWithTag:1000];        //单例传值  将要传递的信息存入单例中(共享中)    //  [[AppStatus shareInstance]setContextStr:tf.text]; 跟下面这种写法是等价的    [AppStatus shareInstance].contextStr = _textField.text;    //导航push到下一个页面    //pushViewController 入栈引用计数+1,且控制权归系统    DetailViewControllerFour *detailViewController = [[DetailViewControllerFour alloc]init];        //导航push到下一个页面    [self.navigationController pushViewController:detailViewController animated:YES];    }#pragma mark - Getter & SetterLabelGetter(label, NSTextAlignmentCenter, ColorFromRGB(0xffffff), [UIFont systemFontOfSize:15])
#import "DetailViewControllerFour.h"#import "AppStatus.h"@interface DetailViewControllerFour ()@property (nonatomic, strong) UILabel *label;@property (nonatomic, strong) UITextField *textField;@end@implementation DetailViewControllerFour- (void)viewDidLoad {    [super viewDidLoad];    // Do any additional setup after loading the view.    self.view.backgroundColor = [UIColor whiteColor];        self.label.frame = CGRectMake(20, 100, CGRectGetWidth(self.view.bounds) -40, 40);    self.label.backgroundColor = [UIColor greenColor];    [self.view addSubview:self.label];        self.textField = [[UITextField alloc] initWithFrame:CGRectMake(20, 200, CGRectGetWidth(self.view.bounds) -40, 40)];    self.textField.placeholder = @"请输入内容";    self.textField.backgroundColor = [UIColor purpleColor];    self.textField.textColor = [UIColor whiteColor];    [self.view addSubview:self.textField];        UIButton *button =[UIButton buttonWithType:UIButtonTypeCustom];    button.frame = CGRectMake(20, 300, CGRectGetWidth(self.view.bounds) -40, 40);    button.backgroundColor = [UIColor redColor];    [button setTitle:@"发送" forState:UIControlStateNormal];    [button addTarget:self action:@selector(doneAction:) forControlEvents:UIControlEventTouchUpInside];        [self.view addSubview:button];}- (void)didReceiveMemoryWarning {    [super didReceiveMemoryWarning];    // Dispose of any resources that can be recreated.}-(void)viewWillAppear:(BOOL)animated {    if ([AppStatus shareInstance].contextStr.length !=0) {        self.label.text = [AppStatus shareInstance].contextStr;    } else {        self.label.text = @"用于现实前面页面传递过来的值";    }}//pop回前一个页面-(void)doneAction:(id)sender {    //单例传值    [AppStatus shareInstance].contextStr = _textField.text;    [self.navigationController popViewControllerAnimated:YES];}#pragma mark - Getter & SetterLabelGetter(label, NSTextAlignmentCenter, ColorFromRGB(0xffffff), [UIFont systemFontOfSize:15])

(五)通知传值 
实践方案:第一个界面中的lable显示第二个界面textField中输入的文本
实践步骤:
首先我们建立一个RootViewControllers和一个DetailViewControllers(root页面的label显示detail页面textField输入的内容),首先我们RootViewController里面注册一个通知监听,并在页面消失时移除该通知(注册与移除需要对应)

#import "RootViewControllerFive.h"#import "DetailViewControllerFive.h"#define xbyNotification @"labelChange"@interface RootViewControllerFive ()@property (nonatomic, strong) UILabel *label;@end@implementation RootViewControllerFive- (void)viewDidLoad {    [super viewDidLoad];    // Do any additional setup after loading the view.    self.view.backgroundColor = [UIColor greenColor];    self.title = @"通知传值";        [self.view addSubview:self.label];        UIButton *button  = [UIButton buttonWithType:UIButtonTypeCustom];    button.frame = CGRectMake(20, 300, CGRectGetWidth(self.view.bounds)-40, 40);    [button setTitle:@"点击" forState:UIControlStateNormal];    [button setTitleColor:[UIColor redColor] forState:UIControlStateNormal];    [button addTarget:self action:@selector(clickAction:) forControlEvents:UIControlEventTouchUpInside];    button.backgroundColor = [UIColor blueColor];    [self.view addSubview:button];}-(void)viewWillAppear:(BOOL)animated {    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(labelTextChange:) name:xbyNotification object:nil];}//一开始准备在这移除消息通知,结果GG了,啥通知都收不到//-(void)viewWillDisappear:(BOOL)animated {//    [super viewDidDisappear:animated];//    [[NSNotificationCenter defaultCenter] removeObserver:self];//}//放在这就好了-(void)dealloc {    [[NSNotificationCenter defaultCenter] removeObserver:self];}-(UILabel *)label {    if (!_label) {        _label = [[UILabel alloc ] initWithFrame:CGRectMake(20, 100, CGRectGetWidth(self.view.bounds)-40, 40)];        _label.textAlignment = NSTextAlignmentCenter;        _label.backgroundColor = [UIColor purpleColor];        _label.text = @"等待接收通知消息";        _label.textColor = [UIColor whiteColor];    }        return _label;}- (void)didReceiveMemoryWarning {    [super didReceiveMemoryWarning];    // Dispose of any resources that can be recreated.}-(void)clickAction:(id)sender {    [self.navigationController pushViewController:[DetailViewControllerFive new] animated:NO];}-(void)labelTextChange:(NSNotification *)sender {    NSDictionary *dic = sender.userInfo;    self.label.text = dic[@"info"];//    NSLog(@"收到通知");}

点击按钮时发送通知

#import "DetailViewControllerFive.h"#define xbyNotification @"labelChange"@interface DetailViewControllerFive ()@property (nonatomic, strong) UITextField *textField;@end@implementation DetailViewControllerFive- (void)viewDidLoad {    [super viewDidLoad];    // Do any additional setup after loading the view.        [self.view addSubview:self.textField];    self.view.backgroundColor = [UIColor whiteColor];        UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];    button.frame = CGRectMake(20, 300, CGRectGetWidth(self.view.bounds)-40, 40);    [button setTitle:@"发送通知" forState:UIControlStateNormal];    button.backgroundColor = [UIColor redColor];    [button addTarget:self action:@selector(clickAction:) forControlEvents:UIControlEventTouchUpInside];        [self.view addSubview:button];}- (void)didReceiveMemoryWarning {    [super didReceiveMemoryWarning];    // Dispose of any resources that can be recreated.}-(UITextField *)textField {        if (!_textField) {        _textField = [[UITextField alloc] initWithFrame:CGRectMake(20, 100, CGRectGetWidth(self.view.bounds) - 40, 40)];    }    _textField.placeholder = @"请输入内容";    _textField.backgroundColor = [UIColor greenColor];        return _textField;}-(void)clickAction:(id)sender {    [[NSNotificationCenter defaultCenter] postNotificationName:xbyNotification object:self userInfo:@{@"info":_textField.text}];    [self.navigationController popViewControllerAnimated:NO];}

小结:注册通知与移除通知需要一一对应,同时通知名称要相同,才能收到该通知发送的消息。


Demo下载
 

1 0