委托模式的构建
在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 <NSObject>
- (void)passHomeAddress:(NSString *)homeAddress cell:(ZDDemoTableViewCell *)cell;
- (void)passPhoneNumber:(NSString *)phoneNumber cell:(ZDDemoTableViewCell *)cell;
@end
@interface ZDDemoTableViewCell : UITableViewCell
@property (nonatomic, weak) id<ZDDemoTableViewCellDelegate> 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 ()<ZDDemoTableViewCellDelegate>
- (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<ZDDemoTableViewCellDelegate>)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.如果有必要,可以通过含有位段的结构体,将委托对象是否响应相关协议的方法缓存起来,以用来优化程序的效率。