之前看objc.io #1 Light View Controllers看到一个非常不错的技巧:从UITableViewController中分离数据源,这样能够减小UITableViewController的规模。同一时候也能让程序有一个比較好的架构。

因为UITableViewController是iOS中使用得最频繁的一个视图控制器,所以这里做下笔记,记录下这个技巧。

首先是故事板(当然也能够用代码 + XIB的组合):

新建一个Cell类,连接故事板中的Outlets,代码例如以下:

  1. #import <UIKit/UIKit.h>
  2.  
  3. @interface Cell : UITableViewCell
  4.  
  5. - (void)configureForData:(NSString *)data;
  6.  
  7. @end
  1. #import "Cell.h"
  2.  
  3. @interface Cell ()
  4.  
  5. @property (weak, nonatomic) IBOutlet UILabel *dataTitleLabel;
  6.  
  7. @property (weak, nonatomic) IBOutlet UIButton *dataDetailLabel;
  8.  
  9. @end
  10.  
  11. @implementation Cell
  12.  
  13. - (void)configureForData:(NSString *)data {
  14. self.dataTitleLabel.text = data;
  15. [self.dataDetailLabel setTitle:@"1" forState:UIControlStateNormal];
  16. }
  17.  
  18. - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
  19. {
  20. self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
  21. if (self) {
  22. // Initialization code
  23. }
  24. return self;
  25. }
  26.  
  27. - (void)awakeFromNib
  28. {
  29. // Initialization code
  30. }
  31.  
  32. - (void)setSelected:(BOOL)selected animated:(BOOL)animated
  33. {
  34. [super setSelected:selected animated:animated];
  35.  
  36. // Configure the view for the selected state
  37. }
  38.  
  39. @end

Cell类中的configureForData方法用于配置Cell中UI的内容。

回到TableViewController类。代码例如以下:

  1. #import "TableViewController.h"
  2. #import "DataSource.h"
  3. #import "Cell.h"
  4.  
  5. @interface TableViewController ()
  6.  
  7. @property (strong, nonatomic) NSArray *array;
  8. @property (strong, nonatomic) DataSource *dataSource;
  9.  
  10. @end
  11.  
  12. @implementation TableViewController
  13.  
  14. - (void)viewDidLoad {
  15. [super viewDidLoad];
  16.  
  17. self.array = @[@"1", @"2", @"3", @"1", @"2", @"3", @"1", @"2", @"3"];
  18.  
  19. [self setupTableView];
  20. }
  21.  
  22. - (void)didReceiveMemoryWarning
  23. {
  24. [super didReceiveMemoryWarning];
  25. // Dispose of any resources that can be recreated.
  26. }
  27.  
  28. /* 设置表格的数据源。并registerNib */
  29. - (void)setupTableView {
  30.  
  31. TableViewCellConfigureBlock configureCell = ^(Cell *cell, NSString *str) {
  32. [cell configureForData:str];
  33. };
  34. self.dataSource = [[DataSource alloc] initWithItems:_array
  35. cellIdentifier:@"Cell"
  36. configureCellBlock:configureCell];
  37. self.tableView.dataSource = self.dataSource;
  38. }
  39.  
  40. #pragma mark - UITableViewDelegate
  41.  
  42. - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
  43. return 100.0;
  44. }
  45.  
  46. - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
  47. NSLog(@"%@", self.array[indexPath.row]);
  48. }
  49.  
  50. @end

当中setupTableView方法将表格的UITableViewDataSource “外包”给TableDataSource类实现。

本类实现UITableViewDelegate。包含点击表格中的某一行的行为。cell的高度等。

最后看看承担表格数据源责任的TableViewDataSource类:

  1. #import <Foundation/Foundation.h>
  2.  
  3. typedef void (^TableViewCellConfigureBlock)(id cell, id item);
  4.  
  5. @interface DataSource : NSObject <UITableViewDataSource>
  6.  
  7. - (id)initWithItems:(NSArray *)anItems
  8. cellIdentifier:(NSString *)aCellIdentifier
  9. configureCellBlock:(TableViewCellConfigureBlock)aConfigureCellBlock;
  10.  
  11. - (id)itemAtIndexPath:(NSIndexPath *)indexPath;
  12.  
  13. @end

首先该类必须遵守UITableViewDataSource托付,然后定义一个配置Cell的Block类型。

该类的实现代码例如以下:

  1. #import "DataSource.h"
  2.  
  3. @interface DataSource ()
  4.  
  5. @property (nonatomic, strong) NSArray *items;
  6. @property (nonatomic, copy) NSString *cellIdentifier;
  7. @property (nonatomic, copy) TableViewCellConfigureBlock configureCellBlock;
  8.  
  9. @end
  10.  
  11. @implementation DataSource
  12.  
  13. #pragma mark - Initialization
  14.  
  15. - (id)init {
  16. // 仅仅能通过initWithItems:cellIdentifier:configureCellBlock:方法初始化
  17. return nil;
  18. }
  19.  
  20. - (id)initWithItems:(NSArray *)anItems
  21. cellIdentifier:(NSString *)aCellIdentifier
  22. configureCellBlock:(TableViewCellConfigureBlock)aConfigureCellBlock
  23. {
  24. self = [super init];
  25.  
  26. if (self) {
  27. self.items = anItems;
  28. self.cellIdentifier = aCellIdentifier;
  29. self.configureCellBlock = [aConfigureCellBlock copy];
  30. }
  31.  
  32. return self;
  33. }
  34.  
  35. - (id)itemAtIndexPath:(NSIndexPath *)indexPath {
  36. return self.items[(NSUInteger) indexPath.row];
  37. }
  38.  
  39. #pragma mark UITableViewDataSource
  40.  
  41. /* Required methods */
  42.  
  43. - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
  44. return self.items.count;
  45. }
  46.  
  47. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
  48. UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:self.cellIdentifier
  49. forIndexPath:indexPath];
  50. id item = [self itemAtIndexPath:indexPath];
  51.  
  52. /**
  53. 之所以把configureCellBlock作为一个属性,是为了该类能够被复用
  54. 仅仅要TableViewController定制了相应的代码块并作为參数传入就能够了
  55.  
  56. 复用的关键:不要被详细的实现代码入侵。仅仅须要调用接口和给出接口就能够了
  57. */
  58. self.configureCellBlock(cell, item);
  59. return cell;
  60. }
  61.  
  62. @end

说下cellForRowAtIndexPath方法中的self.configureCellBlock(cell, item);

这句代码的作用无疑是配置Cell中的内容,一般由用户自己定义的Cell类自行实现,这里没有牵涉不论什么实现细节,从而保证TableViewDataSource类能够非常好地被复用。

执行结果:

顺便传了个Demo上来,有兴趣的能够下载看看。

參考资料:Lighter View Controllers

iOS 从UITableViewController中分离数据源的更多相关文章

  1. iOS中UITableView数据源刷新了,但tableview当中的cell没有刷新

    你会不会遇到通过断点查看数据源模型的确刷新了,但是tableview没有刷新的情况,我遇到了,并通过下面的方法解决了,供大家参考! 在tableview中的数据源代理方法 p.p1 { margin: ...

  2. iOS开发 Xcode8中遇到的问题及改动

      iOS开发 Xcode8中遇到的问题及改动 新版本发布总会有很多坑,也会有很多改动. 一个一个填吧... 一.遇到的问题 1.权限以及相关设置 iOS10系统下调用系统相册.相机功能,或者苹果健康 ...

  3. iOS开发——基础篇——iOS开发 Xcode8中遇到的问题及改动

      iOS开发 Xcode8中遇到的问题及改动 新版本发布总会有很多坑,也会有很多改动. 一个一个填吧... 一.遇到的问题 1.权限以及相关设置 iOS10系统下调用系统相册.相机功能,或者苹果健康 ...

  4. 在iOS应用程序中使用Frida绕过越狱检测

           阿里聚安全在之前的三篇博客中介绍了利用Frida攻击Android应用程序,整个过程仿佛让开发者开启上帝视角,在本篇博客中,我们将会介绍在iOS应用程序中使用Frida绕过越狱检测.即使 ...

  5. iOS学习——tableview中带编辑功能的cell键盘弹出遮挡和收起问题解决

    最近在项目中经常用到UITableView中的cell中带有UITextField或UITextView的情况,然后在这种场景下,当我们点击屏幕较下方的cell进行编辑时,这时候键盘弹出来会出现遮挡待 ...

  6. iOS UITableViewCell UITableVIewController 纯代码开发

    iOS UITableViewCell UITableVIewController 纯代码开发 <原创> .纯代码 自定义UITableViewCell 直接上代码 ////// #imp ...

  7. IOS Swift UITableViewcontroller实现点击空白处隐藏键盘

    在ios开发中,为了方便,我们经常使用UITableViewcontroller,比如搜索界面为了方便可能更多的使用UITableViewcontroller,那么问题就来了,当我点击搜索框的时候会弹 ...

  8. iOS: 在UIViewController 中添加Static UITableView

    如果你直接在 UIViewController 中加入一个 UITableView 并将其 Content 属性设置为 Static Cells,此时 Xcode 会报错: Static table ...

  9. iOS 解决LaunchScreen中图片加载黑屏问题

    iOS 解决LaunchScreen中图片加载黑屏问题 原文: http://blog.csdn.net/chengkaizone/article/details/50478045 iOS 解决Lau ...

随机推荐

  1. 用IHTMLDocument2接口获取页面上想要的数据,代替正则表达式

    原文发布时间为:2010-07-01 -- 来源于本人的百度文章 [由搬家工具导入] 1. 用 IHTMLDocument2::all 获得所有元素; 2. 用 IHTMLElementCollect ...

  2. [LeetCode] Compare Version Numbers 字符串操作

    Compare two version numbers version1 and version2.If version1 > version2 return 1, if version1 &l ...

  3. luogu 1258 小车问题 小学奥数(?)

    题目链接 题意 甲.乙两人同时从A地出发要尽快同时赶到B地.出发时A地有一辆小车,可是这辆小车除了驾驶员外只能带一人.已知甲.乙两人的步行速度一样,且小于车的速度.问:怎样利用小车才能使两人尽快同时到 ...

  4. 组合模式Composite Pattern(转)

    什么是组合模式呢?简单来说组合模式就是将对象合成树形结构以表示“部分整体”的层次结构,组合模式使用户对单个对象和组合对象使用具有一致性. 组合模式(Composite Pattern)有时候又叫部分- ...

  5. 树莓派个人实测 Q&A(最新修改使用Manjaro连接远程桌面) (二)

    以下内容使用和http://www.eeboard.com/bbs/thread-5191-1-1.html所在的帖子一样的风格,不过原作者是window下的操作,本人的都是在manjaro linu ...

  6. Codeforces Gym100814 I.Salem-异或 (ACM International Collegiate Programming Contest, Egyptian Collegiate Programming Contest (2015) Arab Academy for Science and Technology)

    这个题就是二进制,找两个数相应的二进制相对应的位置上数不同的最多的个数.异或写就可以. 一开始还想麻烦了,找出来最大的偶数和最大的奇数,最小的偶数和最小的奇数,但是这样想考虑的不全.因为范围比较小,直 ...

  7. Codeforces 371B Fox Dividing Cheese(简单数论)

    题目链接 Fox Dividing Cheese 思路:求出两个数a和b的最大公约数g,然后求出a/g,b/g,分别记为c和d. 然后考虑c和d,若c或d中存在不为2,3,5的质因子,则直接输出-1( ...

  8. [Python Cookbook] Numpy: Iterating Over Arrays

    1. Using for-loop Iterate along row axis: import numpy as np x=np.array([[1,2,3],[4,5,6]]) for i in ...

  9. 基于ARP的网络扫描工具netdiscover

    基于ARP的网络扫描工具netdiscover   ARP是将IP地址转化物理地址的网络协议.通过该协议,可以判断某个IP地址是否被使用,从而发现网络中存活的主机.Kali Linux提供的netdi ...

  10. 伪造服务钓鱼工具Ghost Phisher

    伪造服务钓鱼工具Ghost Phisher   Ghost Phisher是一款支持有线网络和无线网络的安全审计工具.它通过伪造服务的方式,来收集网络中的有用信息.它不仅可以伪造AP,还可以伪造DNS ...