iOS分享 - 对象间的通信之delegate、notificationCenter与block
在项目开发中,常常会涉及到对象之间的通信,而为了降低对象间的耦合,会采用delegate、notificationCenter、block三种方式来进行实现,对于他们的使用,也许大家都能熟练掌握,但是对于如何创建,初学者也许只是一知半解,本文不讲长篇大论,仅通过简单的实例来帮助大家学习三者的使用,希望对尚不了解以上三者的朋友能带来一定的帮助。
一、delegate
估计大家最常用的delegate就是UITableViewDelegate了,那么我们如何自己写一个代理呢?我们常常会在控制器中监听某个视图中按钮的点击,就以此为例。假如在DTestView中有一个Button,我们要在DTestViewController中对这个按钮的点击进行监听,并在点击Button时传递一个数组给DTestViewController,那么代码如下:
//1、在DTestView.h文件中声明协议并创建协议方法 @class DTestView; @protocol DTestViewDelegate <NSObject> @optional /**点击按钮并传递数组信息*/ - (void)dTestViewDidClickBtn:(DTestView*)dTestView withArr:(NSArray *)position; @end //2、在DTestView.h文件中声明delegate属性@interface DTestView : UIView@property (nonatomic, weak) id <DTestViewDelegate> delegate; @end //3、在DTestView.m文件中Button的点击事件里调用delegate的协议方法 - (void)btnClick { if ([self.delegate respondsToSelector:@selector(dTestViewDidClickBtn:withArr:)]) { NSArray *arr = @["test", "delegate"]; [self.delegate dTestViewDidClickBtn:self withArr:arr]; } }
创建代理总共就3步,怎么样,是不是很简单?但是这之中也有几个需要注意的地方:
1、命名规范:类名+Delegate。
2、@optional关键字:遵循协议后,该协议方法可以不实现,协议方法默认为@required修饰,即遵循协议后必须实现该方法,建议不是必须实现的方法都用@optional修饰。
3、ARC环境下,delegate属性用weak修饰。
4、在调用代理方法前,利用respondsToSelector:方法判断代理方法是否存在。
以上就是创建delegate时的注意事项,大家可以思考下为什么要这么做,如有不明白的地方,欢迎提问,如有不对的地方,欢迎指正。
接下来就是delegate的使用了,简单说下,也是3步:
//1、设置代理 - (void)viewDidLoad { [super viewDidLoad]; dTestView *view = [[dTestView alloc] init]; view.delegate = self; [self.view addSubview:view]; } //2、遵循协议 @interface DTestViewController ()<DTestViewDelegate> //3、实现协议方法 - (void)dTestViewDidClickBtn:(DtestView *)dTestView withArr:(NSArray *)arr { NSLog(@"%@", arr); }
好了,这就是一个简单的delegate的创建与使用。
二、notificationCenter
通知中心相对简单,仍以监听按钮点击并传递一个数组为例,在NTestView中发布通知:
//在Button的addTarget点击事件中发布通知 - (void)btnClick { NSArray *arr = @[@"test", @"notificationCenter"]; [[NSNotificationCenter defaultCenter] postNotificationName:@"点击按钮" object:nil userInfo:arr]; }
完了?完了,就这么简单,接下来在NTestViewController中添加观察者:
//添加观察者 - (void)viewDidLoad { [super viewDidLoad]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(nTestViewDidClickBtn:) name:@"点击按钮" object:nil]; } /**接收到通知时调用该方法*/ - (void)nTestViewDidClickBtn:(NSNotification *)note { NSArray *arr = note.userInfo; NSLog(@"%@", arr); } //移除观察者 - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; }
解释一下参数:
name:通知的名称
object:需要传递的对象
userInfo:发布通知是传递的信息(添加观察者时,默认可以接收该参数)
以上,就是notificationCenter的简单使用。注意:在不需要监听时,一定要移除观察者。
三、block(闭包)
block的简单使用,仍以监听按钮点击并传递一个数组为例:
//1、在BtestView.h文件中,我们可以提供这样一个类方法用于初始化: @interface BTestView : UIView /**block属性*/ @property(nonatomic,copy) void(^arrBlock)(NSArray *); /**初始化方法*/ + (instancetype)bTestViewWithArrBlock:(void(^)(NSArray *arr))arrBlock; @end //2、在BTestView.m文件中,实现该方法: + (instancetype)bTestViewWithaArrBlock:(void(^)(NSArray *arr))arrBlock { BTestView *view = [[BTestView alloc] init]; _arrBlock = arrBlock; return view; } //3、在Button的addTarge点击事件中调用arrBlock - (void)clickBtn { NSArray *arr = @[@"test", @"notificationCenter"]; _arrBlock(arr); }
在NTestViewController中使用block:
- (void)viewDidLoad { [super viewDidLoad]; BTestView *view = [BTestView bTestViewWithArrBlock:^(NSArray *arr){ NSLog(@"%@", arr); }]; [self.view addSubview:view]; }
不知道大家看到block用法的时候有没有一种熟悉感?
注意:block属性要用copy修饰,同时,在使用的时候要注意不要造成循环引用。
至于这三种通信方式具体要用哪一种?这必须结合实际项目才能做出选择,常见的一种说法是:一对多通信用notificationCenter,一对一通信在方法少的情况用block,方法多的情况用delegate。
注意:以上代码均未通过实际测试,本文仅提供简单的使用思路。
iOS分享 - 对象间的通信之delegate、notificationCenter与block的更多相关文章
- NSNotification,NSNotificationCenter的使用、iOS中五种对象间传值的方式
学习内容 NSNitification与NotificationCenter(通知与通知中心) 通知的使用 [[NSNotificationCenter defaultCenter]addObserv ...
- ios delegate 代理模式 观察者模式 不同视图间的通信
delegate,在ios中比比皆是,NSURLConnection(网络请求有),tableView, connectionView,等系统自带 的常见代理.甚至,自己写代码的时候,随意间敲打出了p ...
- iOS开发多线程篇—线程间的通信
iOS开发多线程篇—线程间的通信 一.简单说明 线程间通信:在1个进程中,线程往往不是孤立存在的,多个线程之间需要经常进行通信 线程间通信的体现 1个线程传递数据给另1个线程 在1个线程中执行完特定任 ...
- iOS边练边学--多线程NSOperation介绍,子类实现多线程的介绍(任务和队列),队列的取消、暂停(挂起)和恢复,操作依赖与线程间的通信
一.NSOperation NSOperation和NSOperationQueue实现多线程的具体步骤 先将需要执行的操作封装到一个NSOperation对象中 然后将NSOperation对象添加 ...
- iOS开发多线程篇 04 —线程间的通信
iOS开发多线程篇—线程间的通信 一.简单说明 线程间通信:在1个进程中,线程往往不是孤立存在的,多个线程之间需要经常进行通信 线程间通信的体现 1个线程传递数据给另1个线程 在1个线程中执行完特定任 ...
- C++对象间通信组件,让C++对象“无障碍交流”
介绍 这是很久之前的一个项目了,最近刚好有些时间,就来总结一下吧! 推荐初步熟悉项目后阅读本文: https://gitee.com/smalldyy/easy-msg-cpp 从何而来 这要从我从事 ...
- 如何才能学到Qt的精髓——信号槽之间的无关性,提供了绝佳的对象间通讯方式,QT的GUI全是自己的一套,并且完全开源,提供了一个绝好机会窥视gui具体实现
姚冬,中老年程序员 叶韵.KY Xu.赵奋强 等人赞同 被邀请了很久了,一直在思考,今天终于下决心开始写回答. 这个问题的确是够大的,Qt的代码规模在整个开源世界里也是名列前茅的,这么大的项目其中的精 ...
- 【转】Java学习:Java中的线程之线程间的通信
hello各位小伙伴 今天我们来搞一下 线程之间的通信 ( • ̀ω•́ )✧ 让线程按照我们的想法来执行 两个线程间的通信 这是我们之前的线程. 执行效果:谁抢到资源,谁运行~ 实现线程交替执行: ...
- js 页面间的通信
看了一下公司原来的代码,原页面ajax post返回一个页面完整的HTML,然后再打开一个新页面并输出ajax返回的所有代码到新页面上,在新页面上以表单提交的形式实现重定向. 任凭我想了半天也没想出来 ...
随机推荐
- view ondraw
窗口发生重绘时会被应用程序的窗口框架给调用 要使输出的东西始终能在窗口中看到 就可以使用该函数 窗口从到有的时候就会产生WM_PAINT消息,让窗口发生重绘 这是程序就会执行到ONDRAW函数处 所 ...
- Socket 接收本地短连接并转发为长连接 多线程
import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io. ...
- JavaScript获取Select下拉框Option的Value和Text值的方法
Js获取select下拉列表框各个Option的Value值相对比较容易,不过获取Text值却有点麻烦,对于一个初学JavaScript的 新手来说,可能一时还无从下手,那么就请看下本文的方法,以一个 ...
- i++ 与 ++i 的从字节码层面看二者的区别
/** * javap命令可以对class反汇编得到其字节码文件(此命令并不是jdk8开始的,只不过jdk8中对工具进行加强,增加了一些参数,可通过 javap -help了解) * * 注意: * ...
- 从汇编来看c语言之指针
一.基础研究 将下面的程序编译连接,用debug加载: 首先执行第一条语句: 发现p=(unsigned char *)0x1000;在这里是把1000赋给一个偏移地址为01af.大小为两字节的内存空 ...
- UNIQUE NullAble
一般情况 UNIQUE 不应该出现nullable的 但是如果我们要支持也是有办法的,就是写一个filter. https://msdn.microsoft.com/en-us/library/ms1 ...
- JavaScript 中的非真值
False values 下面这些值将被计算出 false (also known as Falsy values): false undefined null 0 NaN 空字符串 ("& ...
- Android中观察者模式的升入理解
以前对Java中的观察者模式只知道一点皮毛,在接触Android的过程中,逐渐认识到观察者模式是如此的重要,android中许多地方都用到了观察者模式例如ContentResolver操作,来总结一下 ...
- 抛出异常的区别 throw 和throw ex
在面试的过程中提到了异常捕获的的几种用法,之前一直使用但是没有仔细留意,调试程序的过程中发现还是有区别的,主要区别在堆栈信息的起始点不同,下边我们通过实例来看这集中不同的抛出异常的方法. 一般我们推荐 ...
- Android AlertDialog全屏显示去除白色边框
使用styles.xml风格: Style.xml代码 <style name="FullScreenDialog" parent="android:style/T ...