iOS开发中利用消息转发实现多重代理

在iOS开发中,我们经常碰到修改完某处,需要在多个页面进行更新,或者是刷新完数据,要在多个页面进行同步,比如聊天时,给对方昵称添加个备注,需要在资料页,聊天页,聊天列表页等同步进行更新,这个时候如果想用代理实现怎么办呢?其实我们可以利用消息转发来实现多重代理,以满足上面的业务需求。

先补充点东西,在OC中调用一个方法,此处以实例方法为例,如

[p eat];

当这个eat方法不存在时,会到这里

+ (BOOL)resolveInstanceMethod:(SEL)sel{
    return [super resolveInstanceMethod:sel];
}

如果不在上面增加这个eat方法,会到这里

- (id)forwardingTargetForSelector:(SEL)aSelector{
    return [super forwardingTargetForSelector:aSelector];
}

同样如果不在上面那个方法进行转发到其它对象处理eat方法,会到这里

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{
    return [super methodSignatureForSelector:aSelector];
}

此时不进行处理,程序也就崩了'NSInvalidArgumentException', reason: '-[Person eat]: unrecognized selector sent to instance。说了这么多,现在回到正题,我们可以这么处理,

在下面方法中返回一个方法签名
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector 
并在下面方法中实现消息转发,发给每个需要实现这个方法的对象
- (void)forwardInvocation:(NSInvocation *)invocation

过程如下:

- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector {
    NSMethodSignature* signature = [super methodSignatureForSelector:selector];
    if (signature)
        return signature;   
    [_delegates compact];
    if (self.silentWhenEmpty && _delegates.count == 0) {
        return [self methodSignatureForSelector:@selector(description)];
    }
    for (id delegate in _delegates) {//存储了各个对象的代理
        if (!delegate)
            continue;
        signature = [delegate methodSignatureForSelector:selector];
        if (signature)
            break;
    }    
    return signature;
}
- (void)forwardInvocation:(NSInvocation *)invocation {
    SEL selector = [invocation selector];
    BOOL responded = NO;  
    for (id delegate in _delegates) {//遍历存储给个对象的代理,发送给每个要实现代理方法的对象
        if (delegate && [delegate respondsToSelector:selector]) {
            [invocation invokeWithTarget:delegate];
            responded = YES;
        }
    }
    if (!responded && !self.silentWhenEmpty)
        [self doesNotRecognizeSelector:selector];
}

接下来通过一个demo 来具体看下。demo中要实现的功能是在当item1中点击传递消息按钮,item1,item2,item3中对应的控制器打印出收到了这个点击消息(3个控制器都已经加载过页面)。

iOS开发中利用消息转发实现多重代理_第1张图片
demo1.png

首先分别在三个控制器中

[[Manager shareManager] addDelegate:self];//Manager是一个管理者,在里面实现了代理的添加与删除,具体实现见demo。

然后点击时调用Manager中的处理方法

[[Manager shareManager] reciveBottonClick:sender];//放到Manager去实现

接下去就是在Manager中处理业务与通知各个对象

- (void)reciveBottonClick:(UIButton *)button{
    ...... //这里进行业务处理
    [_multiDelegate manager:self didBottonClick:button];//处理完后通知各个对象实现代理方法
}

上面最后一步的

[_multiDelegate manager:self didBottonClick:button];

就是通过刚才所说的找不到方法时返回一个方法签名,再转发消息给多个对象进行实现。此时控制台打印出

2017-03-20 19:35:11.659 MultiDelegateDemo[81609:15766652] 我是item1,接受到了按钮点击的消息,按钮地址是0x7f95eb101490
2017-03-20 19:35:11.659 MultiDelegateDemo[81609:15766652] 我是item2,接受到了按钮点击的消息,按钮地址是0x7f95eb101490
2017-03-20 19:35:11.659 MultiDelegateDemo[81609:15766652] 我是item3,接受到了按钮点击的消息,按钮地址是0x7f95eb101490

每个控制器都实现了

- (void)manager:Manager *)manager didBottonClick:(UIButton *)button{    
    NSLog(@"我是item x,接受到了按钮点击的消息,按钮地址是%p",button);
}

最后附上demo地址https://github.com/JimWithJiang/MultiDelegateDemo,里面已经封装好了实现转发的类,只需要在Manager中添加自己需要的业务。

本文难免有纰漏和错误,如有发现敬请指正,谢谢!

你可能感兴趣的:(iOS开发中利用消息转发实现多重代理)