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

实际开发中,几乎到处都会有用到传值,而传值分为正向传值以及逆(反)向传值,比如从界面一调到界面二,并将值从界面一传递到界面二,将此称之为正向传值;而从界面一调到界面二,再从界面二(或界面二的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、"一对一",就像一个婴儿对象只对应一个保姆对象,对同一个协议,一个对象只能设置一个代理delegate,所以单例对象就不能用代理;
    2、①协议定义时,尽量用关键字@required,和@optional来明确代理是否是必须实现某些方法 ②代理的类型需用id类型,weak修饰,d并写明要遵守的协议 ③就是在调用代理方法的时候需要判断代理是否实现该方法。
  • 举例代码:

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 = 我要调回至第一个控制器
    
}

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

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

    》被监听者 接收通知
    》实现通知方法
  • 通知的注意事项:
    1.跟代理不同的是:代理是一对一(就像一个婴儿对象只对应一个保姆对象),通知是多对多(例如一个tx发布者可以对应n个监听者,同样一个监听者可以监听tx也可以监听wy),就是某个对象想告诉某个对象一些事,或者某个对象想监听某个对象的一些事件。
    2.无论发布通知还是订阅通知,都需要通过消息中心:NSNotificationCenter
    3.订阅了某个消息后,一定要记得在dealloc方法里移除订阅,否则除了性能的问题还会有其他的问题出现。
  • 举例代码:
    1.在* ZWSecondViewController.m*按钮中的点击事件中
- (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本身可以封装一段代码

  • Block的优点:
    1,写法更简练,不需要写protocol、函数等
    2,block注重结果的传输:比如对于一个事件,只想知道成功或者失败,并不需要知道进行了多少或者额外的一些信息。
    3,block需要注意防止循环引用:
    在ARC模式下这样防止:
*__weak typeof(self) weakSelf = self;*
  • Block的注意事项
    1.访问外部变量的问题
    ① 在block代码块的内部可以定义1个和外部的变量名称相同的变量访问的时候,是就近原则.
    ②在block代码块的内部可以去取出外部的全局变量和局部变量的值.但是,在block代码块的内部,可以修改全局变量的值,但是不能修改外部的局部变量的值
    ③如果就是希望在block代码块的内部去修改外部的局部变量的值.那么就给这个局部变量加个__block的修饰符.
  • 举例代码:

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];
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,491评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,856评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,745评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,196评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,073评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,112评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,531评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,215评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,485评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,578评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,356评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,215评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,583评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,898评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,497评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,697评论 2 335

推荐阅读更多精彩内容