iOS写的比较多的就是UITableView,几乎每个控制器里面都有这家伙,在加上网络请求,错误处理,loading动画,UITableViewDataSource,UITableViewDelegate,一个控制器还没怎么写就已经大篇的代码了。
当然,大部分人是不会把这些都写在控制器里然后一遍一遍的粘贴的。解决方法有很多,继承算是常用的一种,或者利用协议的特性也可以达到目的
什么是协议编程
协议的话想对更灵活,定义一个规则,别人可以遵守这个协议,然后实现规定的方法,同时一个类可以有多个协议。
但是这些协议只是相当于接口,遵循某个协议的类只表明实现了这些接口,每个类都需要对这些接口有单独的实现,这就很可能会导致重复代码的产生。我们可以利用一些工具,为协议添加默认的实现,比如说ProtocolKit, 或者libextobjc里面的EXTConcreteProtocol.h
。后面讲大致原理
为什么要用它
下面是个人的浅显理解,理解的错误的地方请轻拍:
我们使用协议的目的,更加灵活,从而降低耦合性,减少冗余性(你可以实现,也可以不实现)。
相比OC,目前Swift里面有很多地方用到协议编程,说明它是一种比较推荐的编程方式
怎么用
本人结合作者的开发经验,讲一讲我对协议编程的理解和具体的使用,我们就拿常见的带UITableView
控制器来举例
我们的目的:减低重复代码,增加可扩展性
细化一下:
- 把网络和网络的loading,放到
RequestViewController
控制器里面 - 一个
BaseTableViewController
继承RequestViewController
,同时把UITableViewDataSource,UITableViewDelegate
方法写到这里面 - 使用一个接口请求以及数据处理的类,里面进行具体的网络请求和请求结果的处理
这样一个控制器里面,就剩下一些自己特定的响应事件、除了UITableView
的其它的UI组件,以及少部分cell代理或者数据源方法,这些也可以抽出去
下面是我从项目冲抽出来的一个Demo的代码片段
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.view.backgroundColor = [UIColor whiteColor];
[self loadData];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return 44;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
id obj = [self.viewModel objectAtIndexPath:indexPath];
// TODO 装配数据--通常情况下,我们会用一个分类来进行cell注册和取
static NSString *ID = @"ID";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];
}
// Configure the cell...
cell.textLabel.text = @"ticsmatic";
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
id obj = [self.viewModel objectAtIndexPath:indexPath];
// TODO 处理点击事件
}
小Demo在这里ConcreteProtocol
补充
简单的讲一下协议的默认实现方式,看ProtocolKit就知道,大约也就200行代码。让你分析一下,一句话就是为类增加方法被呗。把协议的默认实现方法,注入到遵守这个协议的类里面,必然是利用runtime。
具体代码讲解可以看这篇博文如何在 Objective-C 中实现协议扩展
最后
这个Demo写的比较粗糙,仅仅是提供一种思路,里面还有许多可以优化修改的地方。同时,如果我在那里写的不好的可以批评指正