iOS_四大传值

作者: Corbin___ | 来源:发表于2017-04-12 17:32 被阅读36次

    一、目录

    二、掌握四大传值前提

    1.掌握push跳转 相关文章链接:http://www.jianshu.com/p/46f693f761a1
    2.掌握单例模式
    3.掌握block
    4.掌握代理

    三、介绍

    1、属性传值

    (1)、介绍:

    比如A视图要给B视图传值字符“abc”
    1,B视图就声明一个属性NSSTring来接受字符abc
    2,A视图中new一个B控制器,B.NSString = “abc”
    3,这样就赋值过去了

    (2)、代码:
    // B视图的.h文件
    @property (nonatomic,copy) NSString *propertySendString; 
    // 用来接受A视图传递过来的数据
    
    
    // A视图的.m文件
     Delegate *vc = [self.storyboard instantiateViewControllerWithIdentifier:@"delegateVC"];
        vc.propertySendString = @"属性传值";
        [self.navigationController pushViewController:vc animated:YES];
    
    
    (3)、注意:

    在A视图里面new了B视图,这时候跳转到B视图,一定一定一定要把这个new的视图push过去,不然如果是故事版脱线跳转的话,跳转过来的就不是这个new的B控制器了,那么传递肯定是失败的

    2、单例传值

    (1)、介绍:

    单例就是整个APP只有一个对象,比如我把A类设为单例,那么我new的A类对象都是同一样,不会出现第二个的,这样我给A类中的一个变量赋值,那么我在其他视图想要用的时候,我就只需要new这个单例对象去拿这个变量的值就可以了

    (2)、代码
    // 创建一个单例类 这个类的.h文件
    #import <Foundation/Foundation.h>
    
    @interface SingleTon : NSObject
    
    // 传值的属性
    @property (nonatomic,copy) NSString *passValue;
    
    // 创建单例 (单例的命名,shared+类名)
    + (SingleTon *)sharedSingleTom;
    
    @end
    
    
    // 这个类的.m文件
    #import "SingleTon.h"
    
    @implementation SingleTon
    // 以下是创建单例的方法,这是严格的单例,所以代码偏多
    // 严格是创建单例步骤
    static SingleTon *singleTon;
    + (instancetype)allocWithZone:(struct _NSZone *)zone {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            singleTon = [super allocWithZone:zone];
        });
        return singleTon;
    }
    
    + (SingleTon *)sharedSingleTom {
        
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            singleTon = [[SingleTon alloc] init];
        });
        return singleTon;
    }
    
    -(id)copyWithZone:(NSZone *)zone{
        return singleTon;
    }
    
    @end
    
    
    // 比如我A界面想把abc传到B界面,
    // 那么我这个单例类就是传值的中间介质
    // 以下代码就是给单例的变量赋值(赋我要传的值)
    // 比如我在A界面里给单例变量赋值,那么接下来我在B界面里,创建这个单例,然后直接调用这个单例变量,这个变量就是abc的值了
     SingleTon *singleTon = [SingleTon sharedSingleTom];
        singleTon.passValue = @"单例传值";
    
    

    3、block传值

    (1)、介绍

    可以向任何方向传值
    比如我A类中有个值要传出来,那么我就在A类写一个类方法,类方法的参数是block,然后这个block的参数是我要传的值
    这样我在B类就可以用直接用A类调用这个类方法,然后这个类方法的block回调里就会带一个参数,这个参数是带有值的,值就是从A类block参数带出来的

    (2)、代码
    
    // A类的.h文件
    
    #import <Foundation/Foundation.h>
    // 定义一个闭包(block),然后参数是字符串
    typedef void (^sentValue)(NSString *str);
    @interface Block : NSObject
    
    // 定义一个类方法,参数是这个闭包
    + (void)sentValueClick:(sentValue)_sentBlock ;
    
    
    @end
    
    
    // A类的.m文件
    #import "Block.h"
    
    @implementation Block
    
    // 实现.h文件中定义的类方法
    + (void)sentValueClick:(sentValue)_sentBlock {
    
        // 这个给这个闭包传的参数“block传值”就是你要传的值了
        _sentBlock(@"block传值");
        
    }
    
    @end
    
    
    // 你想在哪里拿到这个值,就在哪里调用这个方法,这个str参数就是传出来的值
     [Block sentValueClick:^(NSString *str) {
            NSLog(@"block:%@",str);
        }];
    
    

    4、代理传值

    (1)、介绍:

    代理传值一般用于后向前传值
    比如我A点击跳转到B界面,然后想把B界面的值传递到A界面,并且跳转回A界面
    那么我就在B界面写一个代理和代理方法,然后再B界面视图消失的方法里面调用这个代理方法,这时候由于你已经设置A界面为B的代理对象了,所以在B界面快消失的时候调用代理方法,其实是A界面调用了代理方法,所以这时候就可以把我要传递的值传递过去(有点难理解,具体看下代码)

    (2)、代码
    // B界面.h文件
    #import <Foundation/Foundation.h>
    #import <UIKit/UIKit.h>
    
    
    @protocol SentValueDelegate <NSObject>
    
    @optional
    - (void)sentValueClicked:(NSString *)str;
    
    @end
    
    @interface Delegate : UIViewController
    
    @property (nonatomic,weak) id <SentValueDelegate> delegate;
    
    @property (nonatomic,copy) NSString *propertySendString;
    
    @end
    
    
    //B界面.m文件
    // 视图即将消失会自动调用的方法
    - (void)viewWillDisappear:(BOOL)animated {
        if ([_delegate respondsToSelector:@selector(sentValueClicked:)]) {
            [self.delegate sentValueClicked:@"代理传值"];
        }
    }
    
    
    // A界面的.m文件
    
    // 点击按钮跳转到第二个页面 代理传值(后向前传值)
    - (IBAction)pushClicked:(UIButton *)sender {
        
        Delegate *delegateVC = [self.storyboard instantiateViewControllerWithIdentifier:@"delegateVC"];
        delegateVC.delegate = self;
    
        [self.navigationController pushViewController:delegateVC animated:YES];
    }
    
    
    // 实现代理的方法(这个方法包含着一个参数,这个参数就是从B页面传递过来的值)
    - (void)sentValueClicked:(NSString *)str {
        NSLog(@"%@",str);
    }
    
    
    (3)、补充说明

    对于这个代理,确实有点难理解,这里我说下执行的顺序
    首先是A类的.m文件
    我点击按钮,跳转到B界面,这时候我点击按钮就会来到按钮的监听方法,在这个方法里面new一个B控制器,然后这时候就要设置B的代理为A类,因为这时候要先设置好,等下B类调用代理方法才会来到这里

    // A界面的.m文件
    
    // 点击按钮跳转到第二个页面 代理传值(后向前传值)
    - (IBAction)pushClicked:(UIButton *)sender {
        
        Delegate *delegateVC = [self.storyboard instantiateViewControllerWithIdentifier:@"delegateVC"];
        delegateVC.delegate = self;
    
        [self.navigationController pushViewController:delegateVC animated:YES];
    }
    
    
    // 实现代理的方法(这个方法包含着一个参数,这个参数就是从B页面传递过来的值)
    - (void)sentValueClicked:(NSString *)str {
        NSLog(@"%@",str);
    }
    
    

    跳转到B类后,在B类快要消失的方法写以下代码
    代码的说明:如果delegate这个代理属性响应了这个方法
    if ([_delegate respondsToSelector:@selector(sentValueClicked:)]) {
    如果响应了就执行以下代码,那么这里就是关键了
    我刚才是A类实现代理方法,就是响应就这个方法
    刚才我在A类把delegate = A类控制器(设置了代理),
    所以这时候self.delegate是等于A类控制器的self
    那么以下的代码就相当于[A类的self 调用sentValueClicked]
    [self.delegate sentValueClicked:@"代理传值"];
    那么这时候,程序就会来到A类实现的代理方法,
    看以下代码,这时候,这个方法的参数str就是
    [self.delegate sentValueClicked:@"代理传值"];里面的"代理传值"

    // 实现代理的方法(这个方法包含着一个参数,这个参数就是从B页面传递过来的值)
    - (void)sentValueClicked:(NSString *)str {
        NSLog(@"%@",str);
    }
    

    以上就是代理传值理解的关键地方,如果这个可以理解好,那么代理是怎么执行的也就可以理解好了

    - (void)viewWillDisappear:(BOOL)animated {
        if ([_delegate respondsToSelector:@selector(sentValueClicked:)]) {
            [self.delegate sentValueClicked:@"代理传值"];
        }
    }
    
    

    四、总结

    • 属性 传值 : 前向后

    • 单例 传值 : 任何方向
      主要思想:单例做为一个中介

    • block传值: 任何方向
      主要思想:哪个类要把值传出来,哪个类就写闭包(block),然后自动类方法+闭包参数的方法,把参数传出来

    • 单例 传值: 后向前
      主要思想:哪个类需要把值传出来,就在哪个类写一个代理,然后想要获取到这个值的话,那么就设置自己为这个类的代理对象,然后去实现它的代理方法,通过这个方法的参数拿到值

    五、个人使用心得

    最简单的方式:

    属性传值,但是局限在前向后,为什么呢?
    因为我A类传值给B类,这里最主要的关键实现是,在A类中new一个B类,并且把我要传的值赋值给B类的接受变量,然后把B类的对象push到B界面,这时候在B类用self.接受变量就可以拿到值了
    其实,这里实现的关键,就是B类的对象
    在A类中new B类的对象,进行赋值,在B界面调用self也是这个B类对象,也就是说这是同一个对象,同一块内存空间的,所以,理所当然可以赋值,然后传值过去
    所以大概知道为什么只能前向后了把,因为这个实现的关键就是要控制同一个B类对象,如果我是后向前,那么我B类里面,我就得new一个A类对象,但是如果我是用pop是没办法把A对象传递过去的,也就是说我这时候回到A界面又重新new 了一个A对象,所以传值失败的

    最喜欢的方式:

    block传值:因为这个block可以向任何地方传值,步骤又少

    #######使用最多的方式:
    block传值和属性传值,如果是前向后我会用属性传值,其他情况大多是用block

    相关文章

      网友评论

        本文标题:iOS_四大传值

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