在封装UITableViewDataSource和UITableViewDelegate遇到如下的问题.
HDTableViewManager.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| * HDTableViewManager去实现UITableView的相关协议,简化了UITableView的使用, * 不用重复的实现相关协议,减轻ViewController的负担. */ @interface HDTableViewManager : NSObject <UITableViewDataSource, UITableViewDelegate>
* 省略了其他相关代码 */
* <UITableViewDataSource>,默认为nil */ @property (nonatomic, weak, readwrite) id<UITableViewDataSource> dataSource;
* <UITableViewDelegate>,默认为nil */ @property (nonatomic, weak, readwrite) id<UITableViewDelegate> delegate;
@end
|
HDTableViewManager.m
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| @implementation HDTableViewManager
* 省略了其他相关代码 */
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = nil; if ([self.dataSource respondsToSelector:@selector(tableView:cellForRowAtIndexPath:)]) { cell = [self.dataSource tableView:tableView cellForRowAtIndexPath:indexPath]; } if (!cell) { cell = [[[self class] alloc] initWithStyle:style reuseIdentifier:identifier]; } return cell; }
@end
|
HDTableViewManager内部实现UITableView的相关协议,判断如果HDTableViewManager的dataSource和delegate如果实现相关协议就返回HDTableViewManager的dataSource和delegate.这样一开始是没问题的,但是久而久之随着苹果公司SDK的更新,UITableView的相关协议可能会添加,会删除.HDTableViewManager就需要对相关协议做适配.如果有些协议是无关痛痒的,还要去适配,既不优雅,又累死人.
本着懒人的原则,能不能动态的转发协议.如果HDTableViewManager内部实现了就调用HDTableViewManager的实现,如果HDTableViewManager没有实现,就看dataSource和delegate实现没有,实现了就调用,没有实现就算了.
函数调用流程

方法1
通过重写resolveInstanceMethod固定返回NO,然后通过forwardingTargetForSelector来转发SEL,结果啥反应都没有,不知道是我弄错了还是理解错误.
1 2 3 4 5 6 7 8 9
| + (BOOL)resolveInstanceMethod:(SEL)sel { return NO; }
- (id)forwardingTargetForSelector:(SEL)aSelector {
}
|
方法2
最后通过万能的Google找到了Colin Eberhardt大神的文章,大神在文章中给出了UIScrollViewDelegate的转发,代码如下.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| * 如果self,dataSource,delegate有实现就返回YES. */ - (BOOL)respondsToSelector:(SEL)aSelector { if ([super respondsToSelector:aSelector]) { return YES; } else if ([self.dataSource respondsToSelector:aSelector]) { return YES; } else if ([self.delegate respondsToSelector:aSelector]) { return YES; } else { return NO; } }
* 如果respondsToSelector针对某一个SEL返回是YES,刚刚self没有实现该方法, * 就通过forwardingTargetForSelector转发SEL */ - (id)forwardingTargetForSelector:(SEL)aSelector { if ([self.dataSource respondsToSelector:aSelector]) { return self.dataSource; } else if ([self.delegate respondsToSelector:aSelector]) { return self.delegate; } else { return nil; } }
|
总结
到此就实现了UITableView相关协议的转发,如果以后苹果升级UITableView的协议,也可以动态的去适配,不用苦逼的去写重复的代码.
如果发现文中有啥问题,望指正.
参考链接