美文网首页Object-C键盘上的鼓手iOS
总结iOS 页面间五种传值(属性,代理 , block,单例,通

总结iOS 页面间五种传值(属性,代理 , block,单例,通

作者: MangoJ | 来源:发表于2016-08-01 18:17 被阅读3850次

    废话不多说下面我们就简单介绍下页面间常用的几种传值方式,希望能给初学者带来帮助:

    注: 文中 ,第一个界面为FirstViewController,第二个界面为SecondViewController

    (-)属性传值

    属性传值(场景)一般用于正向传值,即第一个界面传值给第二个界面

    属性传值是这几大传值中最简单的传值方式只需要要记住两点:
    1.要在接收值的界面(SecondViewController)中声明属性即文中: labelString
    2.要在跳转界面的同时将要传的赋值给下个控制器对象的属性即文中的这个操作: secondVc.labelString =textF.text;

    简单的传值代码如下:
    FirstViewController
    #import "FirstViewController.h"
    #import "SecondViewController.h"
    @interface FirstViewController ()
    {
        UITextField * textF;
    }
    @end
    
    @implementation FirstViewController
    
    - (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor =[UIColor whiteColor];
    [self creatUI];
    }
    
    -(void)creatUI{
    //创建输入框
    textF = [[UITextField alloc]init];
    textF.frame = CGRectMake(0, 100, self.view.frame.size.width, 30);
    textF.borderStyle = UITextBorderStyleRoundedRect;
    [self.view addSubview:textF];
    //创建跳转下个界面的按钮
    UIButton * PushBtn = [UIButton buttonWithType:(UIButtonTypeSystem)];
    PushBtn.frame = CGRectMake(0, 140, self.view.frame.size.width, 30);
    [PushBtn setTitle:@"Push" forState:(UIControlStateNormal)];
    [PushBtn addTarget:self action:@selector(PushClick:) forControlEvents:(UIControlEventTouchUpInside)];
    [self.view addSubview:PushBtn];
    
    }
    
    //按钮点击事件
    -(void)PushClick:(UIButton*)sender{
    
    SecondViewController * secondVc = [[SecondViewController alloc]init];
     //赋值给下个控制器的属性
    secondVc.labelString =textF.text;
    [self.navigationController pushViewController:secondVc animated:YES];
    
    }
    
    SecondViewController
    #import <UIKit/UIKit.h>
    
    @interface SecondViewController : UIViewController
    //声明属性:用来接收上个界面传过来的值
    @property (nonatomic,copy) NSString *labelString;
    @end
    
    
    #import "SecondViewController.h"
    
    @implementation SecondViewController
    
    - (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor whiteColor];
    UILabel *label = [[UILabel alloc]init];
    label.frame =CGRectMake(0, 100, self.view.frame.size.width, 30);
    //在标签上展示上个界面传过来的值
    label.text  = _labelString;
    [self.view addSubview:label];
    }
    

    (二)Block传值

    block传值(场景)一般用于逆向传值,即第二个界面传值给第一个界面

    block的用法很多对于初学者来说是个难点,对于传值来说看了本文你可能会觉的并没有那么难,对比属性传值,我们也需要记住两点:
    1.要在第二个界面(SecondViewController.h)定义一个Block:
    #import <UIKit/UIKit.h>
    typedef void (^PushBlock)(NSString*);
    @interface SecondViewController : UIViewController
    @property (nonatomic,strong)PushBlock pushValueString;
    @endpushValueString;
    2.要在第一个界面(FirstViewController.m)跳转第二个界面的方法中我们为block属性赋值完成block传值:

    -(void)PushClick:(UIButton*)sender{
    
    SecondViewController * secondVc = [[SecondViewController alloc]init
    secondVc.pushValueString = ^(NSString *str){
        textF.text =str;
    } ;
    
    [self.navigationController pushViewController:secondVc animated:YES];
    
    }
    
    Block传值完整代码如下:
    FirstViewController
    #import "FirstViewController.h"
    #import "SecondViewController.h"
    @interface FirstViewController ()
    {
    UITextField * textF;
    }
    @end
    
    @implementation FirstViewController
    
    - (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor =[UIColor whiteColor];
    [self creatUI];
    }
    
    -(void)creatUI{
    textF = [[UITextField alloc]init];
    textF.frame = CGRectMake(0, 100, self.view.frame.size.width, 30);
    textF.borderStyle = UITextBorderStyleRoundedRect;
    [self.view addSubview:textF];
    
    UIButton * PushBtn = [UIButton buttonWithType:(UIButtonTypeSystem)];
    PushBtn.frame = CGRectMake(0, 140, self.view.frame.size.width, 30);
    [PushBtn setTitle:@"Push" forState:(UIControlStateNormal)];
    [PushBtn addTarget:self action:@selector(PushClick:) forControlEvents:(UIControlEventTouchUpInside)];
    [self.view addSubview:PushBtn];
    
    }
    //跳转下个界面点击事件
    -(void)PushClick:(UIButton*)sender{
    
    SecondViewController * secondVc = [[SecondViewController alloc]init];
    //核心代码为block属性赋值
    secondVc.pushValueString = ^(NSString *str){
        textF.text =str;
    } ;
    
    [self.navigationController pushViewController:secondVc animated:YES];
    
    }
    
    SecondViewController
    #import <UIKit/UIKit.h>
    typedef void (^PushBlock)(NSString*);
    @interface SecondViewController : UIViewController
    @property (nonatomic,strong)PushBlock pushValueString;
    @end
    
    
    #import "SecondViewController.h"
    
    @interface SecondViewController ()
    {
    
    UITextField * textF;
    NSString * textFString;
    }
    @end
    
    @implementation SecondViewController
    
    - (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor whiteColor];
    textF = [[UITextField alloc]init];
    textF.frame = CGRectMake(0, 100, self.view.frame.size.width, 30);
    textF.borderStyle = UITextBorderStyleRoundedRect;
    [self.view addSubview:textF];
    
    UIButton * Backbtn = [UIButton buttonWithType:(UIButtonTypeSystem)];
    
    Backbtn.frame  =CGRectMake(0, 140, self.view.frame.size.width, 30);
    
    [Backbtn addTarget:self action:@selector(backClick:) forControlEvents:(UIControlEventTouchUpInside)];
    [Backbtn setTitle:@"back" forState:(UIControlStateNormal)];
    [self.view addSubview:Backbtn];
    }
    //返回第一个界面并将值带入
    -(void)backClick:(UIButton*)sender{
    //核心代码
    _pushValueString(textF.text);
    [self.navigationController popViewControllerAnimated:YES];
    }
    

    (三)代理传值

    代理传值(场景)一般用于逆向传值,即第二个界面传值给第一个界面

    FirstViewController页面push到SecondViewController页面,如果SecondViewController页面的信息想回传(回调)到FirstViewController页面,用代理传值,其中SecondViewController定义协议和声明代理,FirstViewController确认并实现代理,FirstViewController作为SecondViewController的代理
    对于代理传值我们要记住如下记步操作:
    第一步:首先,在SecondViewController.h中
    (1).定义协议
    (2).设置协议中的方法
    (3).声明代理
    然后,在SecondViewController.m中
    (1).为其绑定相应方法
    第二步:在FirstViewController.m中
    (1).设置代理
    (2).服从协议

    完整代理传值代码如下:
    SecondViewController
    //首先在SecondViewController.h中创建协议方法
    #import <UIKit/UIKit.h>
    @class SecondViewController;
    //定义协议
    @protocol PushValueDelegate<NSObject>
    @optional
    //设置协议中的方法
    -(void)viewController:(SecondViewController*)ViewController didPushVlaueWithInfo:(id)info;
    @end
    @interface SecondViewController : UIViewController
    //声明代理
    @property (nonatomic,assign)id<PushValueDelegate>delegate;
    @end
    
    
    //然后,在SecondViewController.m中我们判定代理对象存在时,为其绑定相应方法
    #import "SecondViewController.h"
    @interface SecondViewController ()
    {
    UITextField * textF;
    NSString * textFString;
    }
    @end
    @implementation SecondViewController
    -(void)viewWillDisappear:(BOOL)animated{
    //设置视图将要消失时.通过代理传值
    //判断代理是否存在,并且设置代理能够响应代理方法时,才执行代理方法
    if (self.delegate && [self.delegate respondsToSelector:@selector(viewController:didPushVlaueWithInfo:)]) {
        [self.delegate viewController:self didPushVlaueWithInfo:textF.text];
    }
    }
    
    - (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor redColor];
    textF = [[UITextField alloc]init];
    textF.frame = CGRectMake(0, 100, self.view.frame.size.width, 30);
    textF.borderStyle = UITextBorderStyleRoundedRect;
    [self.view addSubview:textF];
    
    }
    
    FirstViewController
    #import "FirstViewController.h"
    #import "SecondViewController.h"
    //服从协议
    @interface FirstViewController ()<PushValueDelegate>
    {
      UITextField * textF;
    }
    @end
    
    @implementation FirstViewController
    
    - (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor =[UIColor whiteColor];
    [self creatUI];
      }
    
    -(void)creatUI{
    textF = [[UITextField alloc]init];
    textF.frame = CGRectMake(0, 100, self.view.frame.size.width, 30);
    textF.borderStyle = UITextBorderStyleRoundedRect;
    [self.view addSubview:textF];
    
    UIButton * PushBtn = [UIButton buttonWithType:(UIButtonTypeSystem)];
    PushBtn.frame = CGRectMake(0, 140, self.view.frame.size.width, 30);
    [PushBtn setTitle:@"Push" forState:(UIControlStateNormal)];
    [PushBtn addTarget:self action:@selector(PushClick:) forControlEvents:(UIControlEventTouchUpInside)];
    [self.view addSubview:PushBtn];
    
    }
    -(void)PushClick:(UIButton*)sender{
    
    SecondViewController * secondVc = [[SecondViewController alloc]init];
    //设置代理
    secondVc.delegate =self;
    
    [self.navigationController pushViewController:secondVc animated:YES];
    
    }
    //实现代理方法
    -(void)viewController:(SecondViewController*)ViewController didPushVlaueWithInfo:(id)info{
    
    textF.text = info;
    
    }
    

    (四)单例传值

    单例可以保证某个类的实例在程序中是唯一的,便于进行资源和数据的共享。

    单例的实现:
    (1)新建一个普通的类,假设名字为People 在People.h中声明一个类方法,到时候使用该类方法(注意:一定是类方法,而不是实例方法)可以创建该类的唯一的一个实例

    #import "Peopel.h"
    @implementation People
    {
      NSString *_eat;
     }
    @property(nonatomic,retain)NSString *eat;
    +(Peopel*)shareInstance;
    @end
    

    (2)在Peopel .m中需要实现sharedInstance方法和你其他的业务逻辑
    #import "Peopel.h"
    //static声明一个类的静态实例;
    static Peopel instrance = nil;
    @implementation Peopel
    //使用类方法生成这个类唯一的实例
    +(Peopel
    )shareInstance{

    if (instrance == nil) {
        instrance = [[super alloc]init];
      }
    return instrance;
    
    }
    @end
    

    注意:一定要声明一个static的静态变量。以后创建类的唯一实例就使用sharedInstance方法,而不是使用alloc ,init.

    下面为单例传值的简单使用(完整代码):
    FirstViewController
    #import "FirstViewController.h"
    #import "SecondViewController.h"
    #import"Peopel.h"
    
    @interface FirstViewController ()
    {
      UITextField * textF;
    }
    @end
    
    @implementation FirstViewController
    
    - (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor =[UIColor whiteColor];
    [self creatUI];
    
    }
    //接收由第二个界面pop回时textF里的数据值
    -(void)viewWillAppear:(BOOL)animated{
    [super viewWillAppear:animated];
    textF.text=[Peopel shareInstance].eat;
    }
    
    -(void)creatUI{
    textF = [[UITextField alloc]init];
    textF.frame = CGRectMake(0, 100, self.view.frame.size.width, 30);
    textF.borderStyle = UITextBorderStyleRoundedRect;
    [self.view addSubview:textF];
    UIButton * PushBtn = [UIButton buttonWithType:(UIButtonTypeSystem)];
    PushBtn.frame = CGRectMake(0, 140, self.view.frame.size.width, 30);
    [PushBtn setTitle:@"Push" forState:(UIControlStateNormal)];
    [PushBtn addTarget:self action:@selector(PushClick:) forControlEvents:(UIControlEventTouchUpInside)];
    [self.view addSubview:PushBtn];
    
    }
    -(void)PushClick:(UIButton*)sender{
    //跳转下个界面的同时为单例属性赋值
     [[Peopel shareInstance]setEat:textF.text];
    SecondViewController * secondVc = [[SecondViewController alloc]init];
    [self.navigationController pushViewController:secondVc animated:YES];    
    }
    
    SecondViewController
    #import "SecondViewController.h"
    #import "Peopel.h"
    @interface SecondViewController ()
    {
    UITextField * textF;
    NSString * textFString;
    }
    @end
    
    @implementation SecondViewController
    -(void)viewWillDisappear:(BOOL)animated{
    }
    -(void)viewWillAppear:(BOOL)animated{
    [super viewWillAppear:animated];
    textF.text = [Peopel shareInstance].eat;
    }
    - (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor redColor];
    textF = [[UITextField alloc]init];
    textF.frame = CGRectMake(0, 100, self.view.frame.size.width, 30);
    textF.borderStyle = UITextBorderStyleRoundedRect;
    textF.text = [Peopel shareInstance].eat;
    [self.view addSubview:textF];
    //返回按钮
    UIButton * Backbtn = [UIButton buttonWithType:(UIButtonTypeSystem)];
    Backbtn.frame  =CGRectMake(0, 140, self.view.frame.size.width, 30);
    [Backbtn addTarget:self action:@selector(backClick:) forControlEvents:(UIControlEventTouchUpInside)];
    [Backbtn setTitle:@"back" forState:(UIControlStateNormal)];
    [self.view addSubview:Backbtn];
    }
    
    -(void)backClick:(UIButton*)sender{
    //返回时为单例属性赋值
    [Peopel shareInstance].eat = textF.text;
    [self.navigationController popViewControllerAnimated:YES];
    }
    

    (五)通知传值

    谁要监听值的变化,谁就注册通知 特别要注意,通知的接受者必须存在这一条件

    1、注册通知
    2、通知中心发送一条消息通知,其中name前后一定要一样
    3、实现通知中心内部的方法,并实现传值
    4、消息发送完,要移除掉。(页面将要消失的时候)

    通知传值的简单代码如下:

    代码为第二个界面传值到第一个界面的实现:

    FirstViewController
    #import "FirstViewController.h"
    #import "SecondViewController.h"
    
    @interface FirstViewController ()
    {
      UITextField * textF;
    }
    @end
    
    @implementation FirstViewController
    - (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor =[UIColor whiteColor];
    [self creatUI];
    /**
     adObserver:注册监听者,一般都是控制器本身去监听一个通知
     selector :当监听到通知的时候执行的方法
     name :通知的名字,要和发送的通知的对象的名字一致
     object: nil
     */
    //注册监听者
    [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(ChangeTextFText:) name:@"ChangeValue" object:nil];
    
    }
    -(void)ChangeTextFText:(NSNotification*)notification{
    NSDictionary * dic = notification.userInfo;
    NSLog(@"%@",dic);
    textF.text = dic[@"Value"];
    }
    
    -(void)creatUI{
    textF = [[UITextField alloc]init];
    textF.frame = CGRectMake(0, 100, self.view.frame.size.width, 30);
    textF.borderStyle = UITextBorderStyleRoundedRect;
    [self.view addSubview:textF];
    UIButton * PushBtn = [UIButton buttonWithType:(UIButtonTypeSystem)];
    PushBtn.frame = CGRectMake(0, 140, self.view.frame.size.width, 30);
    [PushBtn setTitle:@"Push" forState:(UIControlStateNormal)];
    [PushBtn addTarget:self action:@selector(PushClick:) forControlEvents:(UIControlEventTouchUpInside)];
    [self.view addSubview:PushBtn];
    
    }
    -(void)PushClick:(UIButton*)sender{
    SecondViewController * secondVc = [[SecondViewController alloc]init];
    [self.navigationController pushViewController:secondVc animated:YES];
    }
    
    //移除控制器上所有监听的通知
    -(void)dealloc{
    [[NSNotificationCenter defaultCenter]removeObserver:self];
    }
    
    SecondViewController
    #import "SecondViewController.h"
    
    @interface SecondViewController ()
    {
    
      UITextField * textF;
    }
    @end
    
    @implementation SecondViewController
    -(void)viewWillAppear:(BOOL)animated{
    [super viewWillAppear:animated];
    }
    - (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor redColor];
    textF = [[UITextField alloc]init];
    textF.frame = CGRectMake(0, 100, self.view.frame.size.width, 30);
    textF.borderStyle = UITextBorderStyleRoundedRect;
    
    [self.view addSubview:textF];
    
    UIButton * Backbtn = [UIButton buttonWithType:(UIButtonTypeSystem)];
    
    Backbtn.frame  =CGRectMake(0, 140, self.view.frame.size.width, 30);
    
    [Backbtn addTarget:self action:@selector(backClick:) forControlEvents:(UIControlEventTouchUpInside)];
    [Backbtn setTitle:@"back" forState:(UIControlStateNormal)];
    [self.view addSubview:Backbtn];
    }
    
    -(void)backClick:(UIButton*)sender{
    //发送通知
      [[NSNotificationCenter defaultCenter]postNotificationName:@"ChangeValue" object:nil userInfo:@{@"Value":textF.text}];
    [self.navigationController popViewControllerAnimated:YES];
    }
    

    本讲完结:希望能给朋友们的学习带来帮助

    相关文章

      网友评论

      本文标题:总结iOS 页面间五种传值(属性,代理 , block,单例,通

      本文链接:https://www.haomeiwen.com/subject/cpatsttx.html