1.对象通信之委托模式

委托模式的构建

在iOS开发中,对象之间的通信有很多方式,比如说 消息中心(NSNotificationCenter),block,委托模式(delegate),kvo等等,委托模式(delegate)是被开发者在Objective-C中广泛使用的一种通信模式。该模式的主旨可以这样说:“定义一套接口,某对象若想接受另一个对象的委托,则需遵从此接口,以便成为其“委托对象”(delegate)。而这“另一个对象”则可以给其委托对象回传一些信息,也可以在发生相关事件时通知委托对象“<注:Effective Objective-C 2.0 P94>。说白了就是,A想去写篇文章,但是需要电脑,于是他就想买电脑,自己不去,就让B去,那么A让B去买,AB之间通话就构成了委托模式:A委托B去买电脑,B是A的代理,AB之间有个协议,B需要遵守A的协议,去实现A的事情(买电脑)。
好了,废话休说,言归正传。先上代码:

1.定义个协议:
@protocol ZDDemoTableViewCellDelegate 
- (void)passHomeAddress:(NSString *)homeAddress cell:(ZDDemoTableViewCell *)cell;
- (void)passPhoneNumber:(NSString *)phoneNumber cell:(ZDDemoTableViewCell *)cell;
@end

@interface ZDDemoTableViewCell : UITableViewCell
@property (nonatomic, weak) id delegate;
@end

这个ZDDemoTableViewCellDelegate协议的内容有两件事:
1.传出homeAddress和cell
2.传出phoneNumber和cell
另外这里要说一下,这里delegate属性一定要定义成weak,而非strong,因为这俩对象之间的关系不是‘拥有关系’,如果一旦用了strong就会造成 retain cycle 。因此要定义成weak,当然如果你想在相关对象销毁时不需要自动清空,你可以将weak换成unsafe_unretained。

2.然后检测delegate属性能否响应选择子
- (void)homeAddress{
    if ([_delegate respondsToSelector:@selector(passHomeAddress:cell:)]) {
        [_delegate passHomeAddress:@"homeAddress" cell:self];
    }
}
- (void)phoneNumber{
    if ([_delegate respondsToSelector:@selector(passPhoneNumber:cell:)]) {
        [_delegate passPhoneNumber:@"phoneNumber" cell:self];
    }
}
3.最后在你需要的页面遵循协议,执行事件
@interface ViewController ()

- (void)passHomeAddress:(NSString *)homeAddress cell:(ZDDemoTableViewCell *)cell{
    
}
- (void)passPhoneNumber:(NSString *)phoneNumber cell:(ZDDemoTableViewCell *)cell{
    
}
好了,基本的流程就是这个样子了,那么现在我想说的来了。。。。。。

在前面说了,我们需要检测一下委托的对象能不能响应特定的事件(选择子)

- (void)homeAddress{
    if ([_delegate respondsToSelector:@selector(passHomeAddress:cell:)]) {
        [_delegate passHomeAddress:@"homeAddress" cell:self];
    }
}

判断某个委托对象能否响应选择子是必须的,但是如果使用上述的方法,在当这个操作被频繁的执行时,你就会发现,其实只有第一次的判断有用。
为什么呢?因为,委托对象没变,不会发生突然就不执行选择子的情况。所以,我们可以针对这种情况,把这个<某个委托对象响应某个事件(选择子)>记录(缓存)下来,这样去优化效率。

方法

#######1.在实例中嵌入一个含有位段(位域、位字段)的结构体作为实例变量,而结构体中的每个位段表示delegate对象是否实现了协议中的相关的方法。

@interface ZDDemoTableViewCell (){
    struct{
        unsigned int toPassPhoneNumber    :1;
        unsigned int toPassHomeAddress    :1;
    }   _ZDNewDelegate;   
}

#######2.然后重写delegate属性的set方法

#pragma mark重写delegate的Set方法
- (void)setDelegate:(id)delegate{
    [NSNotificationCenter defaultCenter];
    _delegate = delegate;
    _ZDNewDelegate.toPassHomeAddress = [_delegate respondsToSelector:@selector(passHomeAddress:cell:)];
    _ZDNewDelegate.toPassPhoneNumber = [_delegate respondsToSelector:@selector(passPhoneNumber:cell:)];
}

#######3这样在调用delegate相关方法之前,就不用每次都去检测委托对象是否能响应给定的选择子,把之前的代码改成

- (void)homeAddress{
    if (_ZDNewDelegate.toPassHomeAddress) {
        [_delegate passHomeAddress:@"homeAddress" cell:self];
    }
}
- (void)phoneNumber{
    if (_ZDNewDelegate.toPassPhoneNumber) {
        [_delegate passPhoneNumber:@"phoneNumber" cell:self];
    }
}

在相关方法多次调用的时候,值得这样优化。而是否去优化,完全取决你。

总结

1.委托模式为对象提供了一套API,使得其可以将相关事件告知其他对象。
2.如果有必要,可以通过含有位段的结构体,将委托对象是否响应相关协议的方法缓存起来,以用来优化程序的效率。

你可能感兴趣的:(1.对象通信之委托模式)