iOS实现UITableViewDataSource与Controller的分离
写在前面
在之前的项目中好多处用到了tableView,然而之前不懂得将代理方法实现分离,所以每在一处用到tableView就要在controller中写一遍UITableViewDataSource和UITableViewDelegate,实现tableView的基本功能中用到的tableViewDelegate的方法还算不太多,但是说到UITableViewDataSource,里面就那些固定的用法,每次都要写一遍,大大增加了代码的冗余度,虽然不吝啬体力多写几行代码,但是给人感觉不太好,接下来就来说一下怎么样将tableViewDataSource这个磨人的小妖精从controller中分离出来。
创建一个基于NSObject的ArrayDataSource类
这个类就是我们将UITableViewDataSource
分离出来所封装的类。继承协议@interface ArrayDataSource : NSObject<UITableViewDataSource>
。
OK,开始我们的分离之路:
1、
首先在.h文件中,我们定义一个block:typedef void (^TableViewCellConfigureBlock)(id cell, id items);
block中需要的两个参数:第一个参数是cell,第二个参数是数据(这个数据可以是model或者字典)。
2、
在.h文件中写两个作为外部调用的接口:
第一个函数:
@param anItems 传入的盛装数据的数组
@param aCellIdentifier cell的标示符
@param aConfigureCellBlock 回调的block
- (id)initWithItems:(NSArray *)anItems
cellIdentifier:(NSString *)aCellIdentifier
configureCellBlock:(TableViewCellConfigureBlock)aConfigureCellBlock;
第二个函数:
将传入数组中的数据按照cell的indexPath使用(这个我不知道怎么表述清楚,这个方法就是之前在- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
这个函数中将数组中的数据根据cell的索引值给cell中的控件赋值,不知道这样说能不能引起大家的共鸣……^_^)
- (id)itemAtIndexPath:(NSIndexPath *)indexPath;
3、
在.m中,我们声明三个全局变量:
@interface ArrayDataSource ()
@property(nonatomic, strong) NSArray* items;/**< array */
@property(nonatomic, copy) NSString* cellIdentifier;/**< cellIdentifier */
@property(nonatomic, copy) TableViewCellConfigureBlock configureCellBlock;/**< block */
@end
实现.h中的方法:
- (instancetype)init {
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;
}
return self;
}
根据cell的索引值,将传入的数据分离
- (id)itemAtIndexPath:(NSIndexPath *)indexPath {
return self.items[(NSUInteger) indexPath.row];
}
#pragma mark - UITableViewDataSource
实现UITableViewDataSource的方法。。
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.items.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:self.cellIdentifier];
id item = [self itemAtIndexPath:indexPath];
//在这儿将block传出。
self.configureCellBlock(cell, item);
return cell;
}
在Controller中使用
OK,以上的这个类就是我们分离出来的DataSource的类了
在controller中我使用的假数据,将数据放在一个数组arr中,这里我用到了懒加载,在这里我遇到一个困惑就是为什么在if (!_arr)
条件判断中不能使用self.arr,而只能用_arr,但是在if (!_arr) { self.arr = @[@{@"name":@"实现tableViewController的瘦身"}}]; }
中却可以使用self.arr. 我查了一下资料找到答案,_arr是直接值访问,而self.arr是属性访问,就是通过get/set方法来读取这个值,xcode会默认将两个值通过syncthesize关键字进行同步,- (NSArray *)arr
这个方法就是self.arr的get方法,也就是说每次你调用self.arr的时候都会进入这个方法,如果在这个方法里用了下面这个语句if (!self.arr );
逻辑上是行不通的,因为在这里调用self.arr他会再一次进入这个方法,理论上就会死循环,而_arr是直接值访问的,他不会调用get/set方法,所以就不会有这个问题.
那在if (!_arr) {
中使用self.arr,虽然他也会进入get方法,但是他已经不等于nil了.会直接返回他本身,所以没有问题.
self.arr = @[@{@"name":@"实现tableViewController的瘦身"}}];
}
- (NSArray *)arr {
if (!_arr) {
self.arr = @[@{@"name":@"实现tableViewController的瘦身"}}];
}
return _arr;
}
我们在controller中使用tableView的时候需要这样做:
- (void)createTableView {
self.tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
[self.tableView registerClass:[LGJTableViewCell class] forCellReuseIdentifier:@"cell"];
self.tableView.rowHeight = 70;
[self.view addSubview:self.tableView];
//这里我将block中的第二个参数(id items)传入了一个字典。因为我的数据是存放在数组中的字典中的。
TableViewCellConfigureBlock configureCell =^(LGJTableViewCell *cell, NSDictionary *dic) {
//在这里操作cell中的控件,或者给cell中的控件赋值
[cell configData:dic];
};
self.dateSource = [[ArrayDataSource alloc] initWithItems:self.arr cellIdentifier:@"cell" configureCellBlock:configureCell];
self.tableView.dataSource = self.dateSource;
}
总结
经过抽取,我们将dataSource从controller中分离出来,这样不用每次使用tableView的时候我们都要重复写一遍dataSource代理了,同时也简化了代码结构。希望小伙伴们如果觉得有不妥的地方帮我指出来,我们一同进步。end
原文链接:http://www.jianshu.com/p/ee6b57fc335e
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。
iOS实现UITableViewDataSource与Controller的分离的更多相关文章
- iOS实现UICollectionViewDataSource与Controller的分离
之前每次用到UICollectionView的时候都会都需要在Controller里面去实现DataSource & Delegate方法 单独Delegate方法还好不是很多, 但是再加上D ...
- 【IOS笔记】View Controller Basics
View Controller Basics 视图控制器基础 Apps running on iOS–based devices have a limited amount of screen s ...
- iOS UIKit:TabBar Controller
1 结构剖析 IOS中的标签导航其实是一个UITabBarController对象,其也是一个Container View Controller.UITabBarController对象创建和管理了一 ...
- iOS的多版本配置(版本分离,多环境配置)
前几天公司说一个客户要搞一个app,我说搞呗,跟我啥关系...他说,就是从咱的app上搞,什么都一样,就是一些logo啥的不一样.我一开始感觉,那就改改logo呗,后来一想,凑,百度推送,友盟统计,B ...
- iOS push与present Controller的区别
push与present都可以推出新的界面.present与dismiss对应,push和pop对应.present只能逐级返回,push所有视图由视图栈控制,可以返回上一级,也可以返回到根vc,其他 ...
- iOS开发中view controller设置问题
- iOS UITableViewDelegate && UITableViewDataSource 执行顺序
#pragma mark - Table view data source - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableV ...
- iOS开发之--MVC 架构模式
随着项目开发时间的增加,从刚开始那种很随意的代码风格,逐渐会改变,现在就介绍下MVC的架构模式,MVC的架构模式,从字面意思上讲,即:MVC 即 Modal View Controller(模型 视图 ...
- 用Model-View-ViewModel构建iOS App(转)
转载自 Model-View-ViewModel for iOS [译] 如果你已经开发一段时间的iOS应用,你一定听说过Model-View-Controller, 即MVC.MVC是构建iOS a ...
随机推荐
- nodejs进阶(4)—读取图片到页面
我们先实现从指定路径读取图片然后输出到页面的功能. 先准备一张图片imgs/dog.jpg. file.js里面继续添加readImg方法,在这里注意读写的时候都需要声明'binary'.(file. ...
- ASP.NET Core 之 Identity 入门(二)
前言 在 上篇文章 中讲了关于 Identity 需要了解的单词以及相对应的几个知识点,并且知道了Identity处在整个登入流程中的位置,本篇主要是在 .NET 整个认证系统中比较重要的一个环节,就 ...
- ASP.NET Aries 入门开发教程6:列表数据表格的格式化处理及行内编辑
前言: 为了赶进度,周末也写文了! 前几篇讲完查询框和工具栏,这节讲表格数据相关的操作. 先看一下列表: 接下来我们有很多事情可以做. 1:格式化 - 键值的翻译 对于“启用”列,已经配置了格式化 # ...
- SQLServer文件收缩-图形化+命令
汇总篇:http://www.cnblogs.com/dunitian/p/4822808.html#tsql 收缩前 图形化演示: 不仅仅可以收缩日记文件,数据库文件也是可以收缩的,只不过日记收缩比 ...
- Android混合开发之WebViewJavascriptBridge实现JS与java安全交互
前言: 为了加快开发效率,目前公司一些功能使用H5开发,这里难免会用到Js与Java函数互相调用的问题,这个Android是提供了原生支持的,不过存在安全隐患,今天我们来学习一种安全方式来满足Js与j ...
- FFmpeg + SoundTouch实现音频的变调变速
本文使用FFmpeg + SoundTouch实现将音频解码后,进行变调变速处理,并将处理后的结果保存为WAV文件. 主要有以下内容: 实现一个FFmpeg的工具类,保存多媒体文件所需的解码信息 将解 ...
- Configure a VLAN on top of a team with NetworkManager (nmcli) in RHEL7
SOLUTION VERIFIED September 13 2016 KB1248793 Environment Red Hat Enterprise Linux 7 NetworkManager ...
- 程序员必须要知道的Hadoop的一些事实
程序员必须要知道的Hadoop的一些事实.现如今,Apache Hadoop已经无人不知无人不晓.当年雅虎搜索工程师Doug Cutting开发出这个用以创建分布式计算机环境的开源软...... 1: ...
- 关于CSS inline-block、BFC以及外边距合并的几个小问题
CSS inline-block和BCF对于初学者来说,总是弄不太明白,下面记录下我在学习这块知识的过程中遇到的几个问题,供大家参考,有不足的地方,欢迎大家批评指正. 一.在什么场景下会出现外边距合并 ...
- JavaScript作用域
JavaScript作用域 JavaScript作用域一直是前端开发的难题,现在只要用五句话就可解决. 一.“JavaScript中无块级作用域” 在Java或C#中存在块级作用域,即:大括号也是一个 ...