在IOS中为了实现回调通常有以下几个方法:缓存
以上四种中在我本身的项目中比较经常使用的就是delegate和block了。多线程
在现实中回调的需求也分两种架构
对于一对一的回调,在IOS中使用delegate、block都能实现。而一对多的回调基本就是通知中心了。ide
假如如今有一个需求,咱们以图片下载为例。这里先忽略哪些SDWebimage等已经封装好的第三方类库。对于图片下载通常的过程以下:atom
这里的难点是回调。若是一个页面中有多个地方须要显示同一张图片,那么势必会发生这样一种状况,就是同时有多个请求下载赞成url的图片,而且下载完成后须要同时在多个地方显示图片。要是实现这样的需求,用现有的方案貌似很难解决。有的同窗会想到通知中心,可是通知中心实际上是一个广播服务,只要注册了接受该通知那么全部的注册者都能收到通知,但事实上我只须要在我须要下载的那个url的图片下载完后给出通知,而不须要全部的下载完毕事件都通知。这时候咱们就须要多播委托了。url
什么是多播委托?我直接拿其余博客上的一个定义来解释。简单地说,多播委托是指容许建立方法的调用列表或者链表的能力。当多播委托被调用时,列表中的方法均自动执行spa
在IOS中我就以咱们日常用的最多的delagate为例,普通的delegate只能是一对一的回调,没法作到一对多的回调。而多播委托正式对delegate的一种扩展和延伸,多了一个注册和取消注册的过程,任何须要回调的对象都必须先注册。线程
如何在IOS中实现多播委托?老外早就已经写好了,并且至关的好用。我最初接触IOS多播委托是我在研究XMPPframework的时候,而多播委托能够说是XMPPframework架构的核心之一。具体的类名就是GCDMulticastDelegate,从名字就能够看出,这是一个支持多线程的多播委托。那为何要支持多线程呢?个人理解是多个回调有可能不是在同一个线程的,好比我注册回调的时候是在后台线程,可是你回调的时候却在UI线程,那就有可能出问题了。所以必须保证你注册的时候在哪一个线程上注册的,那么回调的时候必须仍是在那个线程上回调的。code
下面我讲解写多播委托在IOS中的用法。orm
我先举个例子,好比有一个UserInfo(有一个userName的属性)的类,页面上有三个lable和一个按钮,当点击按钮的时候给userInfo的userName属性赋值,这时候三个lable同时显示userInfo的userName属性的值。
针对以上过程,咱们须要对每一个lable向userInfo实例注册,也就是向多播委托注册。当对userInfo的userName赋值的时候调用多播委托的方法,这里也就是调用setText方法。这样就能实现上面的需求了。
用代码表示就是:
//继承自多播委托基类的userInfo类 @interface UserInfo : MulticastDelegateBaseObject @property (nonatomic,strong)NSString *userName; @end @implementation UserInfo -(void)setUserName:(NSString *)userName{ _userName=userName; [multicastDelegate setText:userName];//调用多播委托 } @end
- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. //初始化一个userinfo的实例 userInfo=[[UserInfo alloc] init]; //添加一个lable UILabel *lable =[[UILabel alloc] initWithFrame:CGRectMake(0, 20, 100, 30)]; lable.backgroundColor=[UIColor blueColor]; lable.textColor=[UIColor blackColor]; [userInfo addDelegate:lable delegateQueue:dispatch_get_main_queue()];//向多播委托注册 [self.view addSubview:lable]; lable =[[UILabel alloc] initWithFrame:CGRectMake(0, 60, 100, 30)]; lable.backgroundColor=[UIColor blueColor]; lable.textColor=[UIColor blackColor]; [userInfo addDelegate:lable delegateQueue:dispatch_get_main_queue()]; [self.view addSubview:lable]; lable =[[UILabel alloc] initWithFrame:CGRectMake(0, 100, 100, 30)]; lable.backgroundColor=[UIColor blueColor]; lable.textColor=[UIColor blackColor]; [userInfo addDelegate:lable delegateQueue:dispatch_get_main_queue()]; [self.view addSubview:lable]; //添加一个按钮 UIButton *btn=[[UIButton alloc] initWithFrame:CGRectMake(200, 20, 100, 50)]; [btn setBackgroundColor:[UIColor blueColor]]; [btn setTitle:@"button1" forState:UIControlStateNormal]; [btn addTarget:self action:@selector(btnCLicked:) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:btn]; } -(void)btnCLicked:(UIButton *)btn{ userInfo.userName=@"123456";//给userInfo赋值 }