iOS 属性、代理、通知、Block传值

2017-03-02  本文已影响0人  不走寻常way

实际开发中,几乎到处都会有用到传值,而传值分为正向传值以及逆(反)向传值,比如从界面一调到界面二,并将值从界面一传递到界面二,将此称之为正向传值;而从界面一调到界面二,再从界面二(或界面二的TableViewCell中的子控件)返回至界面一并将值传递给界面一的过程,称之为逆(反)向传值。在此,小编将给大家回顾一下实际开发中常用的正向传值以及逆向传值的几种方法,如果不当之处,欢迎指正!

正向传值

最常见的正向传值方式是属性传值,方便简单,理解起来也容易,举例代码如下:

ZWSecondViewController.h文件

#import <UIKit/UIKit.h>

@interface ZWSecondViewController : UIViewController
//在界面二的.h文件中声明一个字符串的属性titleName
@property(nonatomic,copy)NSString *titleName;

@end

ZWFirstViewController.m文件

- (IBAction)clickFirstBtnAction:(id)sender {
    ZWSecondViewController *secondVc = [[ZWSecondViewController alloc] init];
    secondVc.titleName = @"我是第二个控制器";
    [self presentViewController:secondVc animated:YES completion:nil];
}

ZWSecondViewController.m文件

- (void)viewDidLoad {
    [super viewDidLoad];
    ///在界面二的.m文件中可以对该属性的值进行需要的操作
    NSLog(@"%@", self.titleName);//打印结果:我是第二个控制器
}

逆(反)向传值

常见的逆(反)向传值包括代理,通知以及Block,下面一一给大家举例。
一、** 代理**

被代理者
    》设置代理协议
    》创建代理方法
    》设置代理属性
    》判断代理方法
代理者
    》设置代理
    》遵守代理协议
    》实现代理方法

1、ZWSecondViewController.h文件中①设置代理协议,②创建代理方法③设置代理属性

/** 被代理者 **/
#import <UIKit/UIKit.h>

/*1.设置代理协议*/
@protocol ZWSecondDelegate <NSObject>

/*2.创建代理方法*/
//@optional为非必须实现方法,如果没有加@optional,默认为必须实现方法,跟@required一样
@required
//method 传递NSString类型的值
- (void)sendMessage:(NSString *)message;

@end

@interface ZWSecondViewController : UIViewController
//在界面二的.h文件中声明一个字符串的属性titleName
@property(nonatomic,copy)NSString *titleName;

/*3.设置代理属性*/
//声明属性,使用weak修饰
@property(nonatomic,weak)id<ZWSecondDelegate>delegate;

2、ZWSecondViewController.m文件中④判断代理方法

- (void)clickSecondBtnAction:(UIButton *)btn {
    /*4.判断代理方法*/
    if (self.delegate && [self.delegate respondsToSelector:@selector(sendMessage:)]) {
        //赋值前验证代理方法是否存在,存在则赋值
        [self.delegate sendMessage:@"我要调回至第一个控制器"];
    }
    //返回上一个控制器
    [self dismissViewControllerAnimated:YES completion:nil];
}

3、ZWFirstViewController.m文件中①设置代理,②遵守代理协议③实现代理方法

/** 代理者 **/
#import "ZWFirstViewController.h"
#import "ZWSecondViewController.h"

/*2.遵守代理协议*/
@interface ZWFirstViewController ()<ZWSecondDelegate>

@end

@implementation ZWFirstViewController

- (IBAction)clickFirstBtnAction:(id)sender {
    ZWSecondViewController *secondVc = [[ZWSecondViewController alloc] init];
    /*1.设置代理*/
    secondVc.delegate = self;
    [self presentViewController:secondVc animated:YES completion:nil];
}
/*3.实现代理方法*/
- (void)sendMessage:(NSString *)message {
    NSLog(@"message = %@",message);//打印结果:message = 我要调回至第一个控制器
    
}

二、** 通知**
“一对多”,在实际开发中,很多控制器都需要知道一个事件,应该用通知;而且可以在任意对象之间传递,不需要二者有联系,这也是使用通知的优点。当然他的实现和代理相比较稍微绕一点,注册,发通知,收通知

    》获取通知中心对象
    》添加监听者和监听的对象
    》销毁

    》被监听者 接收通知
    》实现通知方法
- (void)clickSecondBtnAction:(UIButton *)ban {
    /** 1.通过消息中心NSNotificationCenter发送通知消息*/

    /**
     NotificationName:通知名称,此处为sendMessage
     object:发通知的对象
     userInfo:发通知附带的额外消息
     */
    [ [NSNotificationCenter defaultCenter] postNotificationName:@"sendMessage" object:self userInfo:@{@"message":@"返回第一个控制器"}];
    //返回上一个界面
    [self dismissViewControllerAnimated:YES completion:nil];
}

2.在ZWFirstViewController.m文件中

- (void)viewDidLoad {
    [super viewDidLoad];
    //2、注册观察者
    /**
     Observer:监听者
     selector:通知方法
     name:通知名称 
     object:nil代表所有的"sendMessage"消息不管是谁发出的,我都订阅,如果为某个对象,就代表只接受该对象发出的通知
     */
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(achiveMessage:) name:@"sendMessage" object:nil];
}
- (void)achiveMessage:(NSNotification *)notification {
    //传递的值保存在通知的userInfo中
    NSDictionary * dic = notification.userInfo;
    
    //在此对传输的数据进行需要的操作
    NSLog(@"message = %@", [dic objectForKey:@"message"]); //打印结果:message = 返回第一个控制器
}
//4、重写dealloc方法移除通知   如果不移除有可能会造成程序崩溃
- (void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

三、** Block**
Block是目前开发最常用的一种方式,功能比较强大,但是在理解和使用上可能需要一段时间摸索和熟悉。他的最大特点就是回调,而且回调时可以传入参数,最重要的是,无论在哪调用,block的执行都会回到block创建的地方执行,而非调用的地方。而block本身可以封装一段代码

*__weak typeof(self) weakSelf = self;*

1.ZWSecondViewController.h文件中定义一个block类型的属性, 属性名为myBlock的属性,

#import <UIKit/UIKit.h>

@interface ZWSecondViewController : UIViewController

//1.定义带两个NSString类型的参数的myBlock属性
@property(nonatomic,copy)void(^myBlock)(NSString *,NSString *);
@end

2.ZWSecondViewController.m文件中

- (void)clickSecondBtnAction:(UIButton *)btn {
    //2、给block属性赋值  传递参数
    //执行存储在block变量中的代码
    self.myBlock(@"我要返回第一个控制器",@"这是我传回来的值");
    //返回上一个界面
    [self dismissViewControllerAnimated:YES completion:nil];
}

3.ZWFirstViewController.m文件中

- (IBAction)clickFirstBtnAction:(id)sender {
    ZWSecondViewController *secondVc = [[ZWSecondViewController alloc] init];
    secondVc.myBlock = ^(NSString *str1,NSString *str2){
        //此处的str1和str2为回调的参数,在此可以对此参数进行相应的操作使用
        NSLog(@"str1 = %@", str1);    //打印结果:str1 = 我要返回第一个控制器
        NSLog(@"str2 = %@", str2);    //打印结果:str2 = 这是我传回来的值
    };
    [self presentViewController:secondVc animated:YES completion:nil];
}
上一篇 下一篇

猜你喜欢

热点阅读