iOS 从UITableViewController中分离数据源
之前看objc.io #1 Light View Controllers看到一个非常不错的技巧:从UITableViewController中分离数据源,这样能够减小UITableViewController的规模。同一时候也能让程序有一个比較好的架构。
因为UITableViewController是iOS中使用得最频繁的一个视图控制器,所以这里做下笔记,记录下这个技巧。
首先是故事板(当然也能够用代码 + XIB的组合):
新建一个Cell类,连接故事板中的Outlets,代码例如以下:
- #import <UIKit/UIKit.h>
- @interface Cell : UITableViewCell
- - (void)configureForData:(NSString *)data;
- @end
- #import "Cell.h"
- @interface Cell ()
- @property (weak, nonatomic) IBOutlet UILabel *dataTitleLabel;
- @property (weak, nonatomic) IBOutlet UIButton *dataDetailLabel;
- @end
- @implementation Cell
- - (void)configureForData:(NSString *)data {
- self.dataTitleLabel.text = data;
- [self.dataDetailLabel setTitle:@"1" forState:UIControlStateNormal];
- }
- - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
- {
- self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
- if (self) {
- // Initialization code
- }
- return self;
- }
- - (void)awakeFromNib
- {
- // Initialization code
- }
- - (void)setSelected:(BOOL)selected animated:(BOOL)animated
- {
- [super setSelected:selected animated:animated];
- // Configure the view for the selected state
- }
- @end
Cell类中的configureForData方法用于配置Cell中UI的内容。
回到TableViewController类。代码例如以下:
- #import "TableViewController.h"
- #import "DataSource.h"
- #import "Cell.h"
- @interface TableViewController ()
- @property (strong, nonatomic) NSArray *array;
- @property (strong, nonatomic) DataSource *dataSource;
- @end
- @implementation TableViewController
- - (void)viewDidLoad {
- [super viewDidLoad];
- self.array = @[@"1", @"2", @"3", @"1", @"2", @"3", @"1", @"2", @"3"];
- [self setupTableView];
- }
- - (void)didReceiveMemoryWarning
- {
- [super didReceiveMemoryWarning];
- // Dispose of any resources that can be recreated.
- }
- /* 设置表格的数据源。并registerNib */
- - (void)setupTableView {
- TableViewCellConfigureBlock configureCell = ^(Cell *cell, NSString *str) {
- [cell configureForData:str];
- };
- self.dataSource = [[DataSource alloc] initWithItems:_array
- cellIdentifier:@"Cell"
- configureCellBlock:configureCell];
- self.tableView.dataSource = self.dataSource;
- }
- #pragma mark - UITableViewDelegate
- - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
- return 100.0;
- }
- - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
- NSLog(@"%@", self.array[indexPath.row]);
- }
- @end
当中setupTableView方法将表格的UITableViewDataSource “外包”给TableDataSource类实现。
本类实现UITableViewDelegate。包含点击表格中的某一行的行为。cell的高度等。
最后看看承担表格数据源责任的TableViewDataSource类:
- #import <Foundation/Foundation.h>
- typedef void (^TableViewCellConfigureBlock)(id cell, id item);
- @interface DataSource : NSObject <UITableViewDataSource>
- - (id)initWithItems:(NSArray *)anItems
- cellIdentifier:(NSString *)aCellIdentifier
- configureCellBlock:(TableViewCellConfigureBlock)aConfigureCellBlock;
- - (id)itemAtIndexPath:(NSIndexPath *)indexPath;
- @end
首先该类必须遵守UITableViewDataSource托付,然后定义一个配置Cell的Block类型。
该类的实现代码例如以下:
- #import "DataSource.h"
- @interface DataSource ()
- @property (nonatomic, strong) NSArray *items;
- @property (nonatomic, copy) NSString *cellIdentifier;
- @property (nonatomic, copy) TableViewCellConfigureBlock configureCellBlock;
- @end
- @implementation DataSource
- #pragma mark - Initialization
- - (id)init {
- // 仅仅能通过initWithItems:cellIdentifier:configureCellBlock:方法初始化
- return nil;
- }
- - (id)initWithItems:(NSArray *)anItems
- cellIdentifier:(NSString *)aCellIdentifier
- configureCellBlock:(TableViewCellConfigureBlock)aConfigureCellBlock
- {
- self = [super init];
- if (self) {
- self.items = anItems;
- self.cellIdentifier = aCellIdentifier;
- self.configureCellBlock = [aConfigureCellBlock copy];
- }
- return self;
- }
- - (id)itemAtIndexPath:(NSIndexPath *)indexPath {
- return self.items[(NSUInteger) indexPath.row];
- }
- #pragma mark UITableViewDataSource
- /* Required methods */
- - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
- return self.items.count;
- }
- - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
- UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:self.cellIdentifier
- forIndexPath:indexPath];
- id item = [self itemAtIndexPath:indexPath];
- /**
- 之所以把configureCellBlock作为一个属性,是为了该类能够被复用
- 仅仅要TableViewController定制了相应的代码块并作为參数传入就能够了
- 复用的关键:不要被详细的实现代码入侵。仅仅须要调用接口和给出接口就能够了
- */
- self.configureCellBlock(cell, item);
- return cell;
- }
- @end
说下cellForRowAtIndexPath方法中的self.configureCellBlock(cell, item);
这句代码的作用无疑是配置Cell中的内容,一般由用户自己定义的Cell类自行实现,这里没有牵涉不论什么实现细节,从而保证TableViewDataSource类能够非常好地被复用。
执行结果:
顺便传了个Demo上来,有兴趣的能够下载看看。
iOS 从UITableViewController中分离数据源的更多相关文章
- iOS中UITableView数据源刷新了,但tableview当中的cell没有刷新
你会不会遇到通过断点查看数据源模型的确刷新了,但是tableview没有刷新的情况,我遇到了,并通过下面的方法解决了,供大家参考! 在tableview中的数据源代理方法 p.p1 { margin: ...
- iOS开发 Xcode8中遇到的问题及改动
iOS开发 Xcode8中遇到的问题及改动 新版本发布总会有很多坑,也会有很多改动. 一个一个填吧... 一.遇到的问题 1.权限以及相关设置 iOS10系统下调用系统相册.相机功能,或者苹果健康 ...
- iOS开发——基础篇——iOS开发 Xcode8中遇到的问题及改动
iOS开发 Xcode8中遇到的问题及改动 新版本发布总会有很多坑,也会有很多改动. 一个一个填吧... 一.遇到的问题 1.权限以及相关设置 iOS10系统下调用系统相册.相机功能,或者苹果健康 ...
- 在iOS应用程序中使用Frida绕过越狱检测
阿里聚安全在之前的三篇博客中介绍了利用Frida攻击Android应用程序,整个过程仿佛让开发者开启上帝视角,在本篇博客中,我们将会介绍在iOS应用程序中使用Frida绕过越狱检测.即使 ...
- iOS学习——tableview中带编辑功能的cell键盘弹出遮挡和收起问题解决
最近在项目中经常用到UITableView中的cell中带有UITextField或UITextView的情况,然后在这种场景下,当我们点击屏幕较下方的cell进行编辑时,这时候键盘弹出来会出现遮挡待 ...
- iOS UITableViewCell UITableVIewController 纯代码开发
iOS UITableViewCell UITableVIewController 纯代码开发 <原创> .纯代码 自定义UITableViewCell 直接上代码 ////// #imp ...
- IOS Swift UITableViewcontroller实现点击空白处隐藏键盘
在ios开发中,为了方便,我们经常使用UITableViewcontroller,比如搜索界面为了方便可能更多的使用UITableViewcontroller,那么问题就来了,当我点击搜索框的时候会弹 ...
- iOS: 在UIViewController 中添加Static UITableView
如果你直接在 UIViewController 中加入一个 UITableView 并将其 Content 属性设置为 Static Cells,此时 Xcode 会报错: Static table ...
- iOS 解决LaunchScreen中图片加载黑屏问题
iOS 解决LaunchScreen中图片加载黑屏问题 原文: http://blog.csdn.net/chengkaizone/article/details/50478045 iOS 解决Lau ...
随机推荐
- 用IHTMLDocument2接口获取页面上想要的数据,代替正则表达式
原文发布时间为:2010-07-01 -- 来源于本人的百度文章 [由搬家工具导入] 1. 用 IHTMLDocument2::all 获得所有元素; 2. 用 IHTMLElementCollect ...
- [LeetCode] Compare Version Numbers 字符串操作
Compare two version numbers version1 and version2.If version1 > version2 return 1, if version1 &l ...
- luogu 1258 小车问题 小学奥数(?)
题目链接 题意 甲.乙两人同时从A地出发要尽快同时赶到B地.出发时A地有一辆小车,可是这辆小车除了驾驶员外只能带一人.已知甲.乙两人的步行速度一样,且小于车的速度.问:怎样利用小车才能使两人尽快同时到 ...
- 组合模式Composite Pattern(转)
什么是组合模式呢?简单来说组合模式就是将对象合成树形结构以表示“部分整体”的层次结构,组合模式使用户对单个对象和组合对象使用具有一致性. 组合模式(Composite Pattern)有时候又叫部分- ...
- 树莓派个人实测 Q&A(最新修改使用Manjaro连接远程桌面) (二)
以下内容使用和http://www.eeboard.com/bbs/thread-5191-1-1.html所在的帖子一样的风格,不过原作者是window下的操作,本人的都是在manjaro linu ...
- Codeforces Gym100814 I.Salem-异或 (ACM International Collegiate Programming Contest, Egyptian Collegiate Programming Contest (2015) Arab Academy for Science and Technology)
这个题就是二进制,找两个数相应的二进制相对应的位置上数不同的最多的个数.异或写就可以. 一开始还想麻烦了,找出来最大的偶数和最大的奇数,最小的偶数和最小的奇数,但是这样想考虑的不全.因为范围比较小,直 ...
- 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( ...
- [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 ...
- 基于ARP的网络扫描工具netdiscover
基于ARP的网络扫描工具netdiscover ARP是将IP地址转化物理地址的网络协议.通过该协议,可以判断某个IP地址是否被使用,从而发现网络中存活的主机.Kali Linux提供的netdi ...
- 伪造服务钓鱼工具Ghost Phisher
伪造服务钓鱼工具Ghost Phisher Ghost Phisher是一款支持有线网络和无线网络的安全审计工具.它通过伪造服务的方式,来收集网络中的有用信息.它不仅可以伪造AP,还可以伪造DNS ...