一个架构合理的UITableView应该是如何的?
原文: http://www.chentoo.com/?p=200
iOS 开发中,UITableView 应该是最经常使用到的了。完毕一个UITableView应该实现他的DataSource和Delegate来讲数据Model填充进View(Cell)中。大家也是知晓的。可是一个UITableView应该如何才干实现良好的架构,事实上非常多人是不在意的。而这也是一个刚開始学习的人和一个工作多年的人最大的区别。
一、MVC
首先我们要谈论的是MVC。这并不奇怪。iOS开发整个的架构体系,就是一个经典的MVC。 Model层负责数据,View层负责展现,Controller层负责协调和处理。而不论你使用UITableViewController 还是 UIViewController中有一个UITableView,你的UITableView 的 DataSource 的几个方法,都应该起到一个Controller的作用。而不应该在其中进行Model层数据的处理,或者View层视图的改动。
二、改怎么做
空洞的话说完了,怎么做呢?我们就从头開始实现一个UITableView。新建一个project。DemoTableView改动ViewController.m,给当前视图增加一个UITabelView。
#import "ViewController.h" @interface ViewController () <UITableViewDataSource, UITableViewDelegate> @property (strong, nonatomic) UITableView *tableView; @end @implementation ViewController - (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib. _tableView = [[UITableView alloc] initWithFrame:self.view.bounds];
_tableView.dataSource = self;
_tableView.delegate = self;
[self.view addSubview:self.tableView]; } @end
假设我们如今尝试执行。肯定是出错的,由于我们没有实现DataSource和Delegate。在实现DataSource之前,让我们先准备号数据源Model。
2.1 Model
新建一个Model类:DemoObject。
它有两个属性title 和 content。
//
// DemoObject.h
// DemoTableView
//
// Created by xiazhidi on 15/3/12.
// #import <Foundation/Foundation.h> @interface DemoObject : NSObject @property (strong, nonatomic) NSString *title;
@property (strong, nonatomic) NSString *content; @end
Model层做到这里就完成了,Model的获取,改动什么的都一股脑丢到ViewController里甚至TableView的DateSoucre里进行。可是合理的架构应该是这种。我们应该在Model层封装好全部的数据请求和处理逻辑,而仅仅暴露出获取的接口提供给Controller层使用。
我们新建一个Category : DemoObject+Api。在这其中封装好Model的获取和处理逻辑。
//
// DemoObject+Api.h
// DemoTableView
//
// Created by xiazhidi on 15/3/12.
// Copyright (c) 2015年 baixing. All rights reserved.
// #import "DemoObject.h" typedef void(^DemoObjectFetchCompletionBlock)(NSArray *demoObjects, NSError *error); @interface DemoObject (Api) + (void)fetchWithCompletionBlock:(DemoObjectFetchCompletionBlock)completionBlock; @end
能够看到,我们提供了一个类方法暴露给Controller层,让它能够方便的获取数据,数据通过Block返回。当然你也能够用Delegate实现,这个看个人习惯。对应的。.m的实现例如以下:(我们仅仅是造一些假数据,真实应用中肯定要设计从网络获取)
//
// DemoObject+Api.m
// DemoTableView
//
// Created by xiazhidi on 15/3/12.
// Copyright (c) 2015年 baixing. All rights reserved.
// #import "DemoObject+Api.h" @implementation DemoObject (Api) + (void)fetchWithCompletionBlock:(DemoObjectFetchCompletionBlock)completionBlock
{
NSMutableArray *mArray = [[NSMutableArray alloc] initWithCapacity:10]; for (NSInteger i = 0; i < 10; i++)
{
DemoObject *demoObject = [[DemoObject alloc] init];
demoObject.title = [NSString stringWithFormat:@"这是第%lu个标题", (unsigned long)i];
demoObject.content = [NSString stringWithFormat:@"这是第%lu个内容", (unsigned long)i];
[mArray addObject:demoObject];
} if (completionBlock)
{
completionBlock([mArray copy], nil);
}
} @end
2.2 View
对于UITableView的View层来说,就是我们要建立一个 Cell ,能够用Xib也能够不用。
那我们这里就用吧。毕竟正式项目中,autolayout什么的用起来还是方便的。新建DemoTableViewCell,放好两个label,连连线什么的就不讲了。详细可看后面附的源代码。关键是,我们须要在cell中,实现cell的配置逻辑。所以我们建立了一个category
//
// DemoTableViewCell+Configure.h
// DemoTableView
//
// Created by xiazhidi on 15/3/12.
// Copyright (c) 2015年 baixing. All rights reserved.
// #import "DemoTableViewCell.h"
@class DemoObject; @interface DemoTableViewCell (Configure) - (void)configureWithDemoObject:(DemoObject *)demoObject; @end
// DemoTableViewCell+Configure.m
// DemoTableView
//
// Created by xiazhidi on 15/3/12.
// Copyright (c) 2015年 baixing. All rights reserved.
// #import "DemoTableViewCell+Configure.h"
#import "DemoObject.h" @implementation DemoTableViewCell (Configure) - (void)configureWithDemoObject:(DemoObject *)demoObject
{
self.titleLabel.text = demoObject.title;
self.contentLabel.text = demoObject.content;
} @end
暴露了一个接口给Controller来实现view的配置。 这种长处是,Controller层不会堆积非常多的代码让人头痛(想想一个复杂的cell可能会有多少须要配置的UI元素),而且会非常方便的方便Cell的复用。
2.3 Controller
我们再来看看如今Controller层详细实现的代码,层次会十分清晰。
//
// ViewController.m
// DemoTableView
//
// Created by xiazhidi on 15/3/12.
// Copyright (c) 2015年 baixing. All rights reserved.
// #import "ViewController.h"
#import "DemoObject+Api.h"
#import "DemoTableViewCell+Configure.h" @interface ViewController () <UITableViewDataSource, UITableViewDelegate> @property (strong, nonatomic) UITableView *tableView; @property (strong, nonatomic) NSArray *demos; @end @implementation ViewController - (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib. _tableView = [[UITableView alloc] initWithFrame:self.view.bounds];
_tableView.dataSource = self;
_tableView.delegate = self;
[_tableView registerNib:[UINib nibWithNibName:@"DemoTableViewCell" bundle:nil] forCellReuseIdentifier:DemoTableViewCellReuseIdentifier];
[self.view addSubview:self.tableView]; __weak ViewController *weakSelf = (ViewController *)self; [DemoObject fetchWithCompletionBlock:^(NSArray *demoObjects, NSError *error) {
if (!error)
{
weakSelf.demos = demoObjects;
[weakSelf.tableView reloadData];
}
}];
} #pragma mark - UITableViewDataSource - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.demos.count;
} - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 60.0f;
} - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
DemoTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:DemoTableViewCellReuseIdentifier forIndexPath:indexPath]; [cell configureWithDemoObject:self.demos[indexPath.row]]; return cell;
} @end
三、总结
以上是一个简单的UITableView的小样例,事实上这样做的目的,就是为了给Controller瘦身,让代码逻辑更清晰。让结构更合理。另外另一些优化的空间,比方把DateSource独立出来成为一个类。这样在Controller其中不在出现DateSource的代码,会更加清爽,可是个人喜好,我不是非常喜欢这样做。以上的样例源代码,在以下能够下载。https://github.com/chentoo/DemoTableView
一个架构合理的UITableView应该是如何的?的更多相关文章
- 一个4年工作经验的java程序员的困惑,怎样才能能为一个架构师,请教大神
一个4年工作经验的java程序员的困惑,怎样才能能为一个架构师 LZ本人想往架构师发展, 业余时间也会看一些书籍, 但是感觉没有头绪, 有些书看了,也没有地方实践 我做了4年的java开发, 在一个公 ...
- 简单了解Flux,注意这是一个设计思想,是一个架构!!!!!
在RN开发中,我们总是需要去更改一个组件个数据(也就是所谓的状态),我们一般是采用是在初始化的函数constror()(好像拼错了) 在这个函数里面申明我们的初始化数据(状态)eg:this.stat ...
- 通向高可扩展性之路(推特篇) ---- 一个推特用来支撑1亿5千万活跃用户、30万QPS、22MB每秒Firehose、以及5秒内推送信息的架构
原文链接:http://highscalability.com/blog/2013/7/8/the-architecture-twitter-uses-to-deal-with-150m-active ...
- 怎样成为PHP 方向的一个合格的架构师
突然看到这篇文章, 值得反省, 乐在其中, 在接下来的发展中不被淘汰的都来看看, 如何成为一个架构师先明确这里所指的PHP工程师,是指主要以PHP进行Web系统的开发,没有使用其的语言工作过.工作经验 ...
- 怎样成为PHP 方向的一个合格的架构师(转)
突然看到这篇文章, 值得反省, 乐在其中, 在接下来的发展中不被淘汰的都来看看, 如何成为一个架构师先明确这里所指的PHP工程师,是指主要以PHP进行Web系统的开发,没有使用其的语言工作过.工作经验 ...
- 要成为一个 Java 架构师得学习哪些知识?
作者:zhuqz链接:https://www.zhihu.com/question/29031276/answer/54631312来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请 ...
- 转: GUI应用程序架构的十年变迁:MVC,MVP,MVVM,Unidirectional,Clean
十年前,Martin Fowler撰写了 GUI Architectures 一文,至今被奉为经典.本文所谈的所谓架构二字,核心即是对于对于富客户端的 代码组织/职责划分 .纵览这十年内的架构模式变迁 ...
- GUI应用程序架构的十年变迁:MVC,MVP,MVVM,Unidirectional,Clean
十年前,Martin Fowler撰写了 GUI Architectures 一文,至今被奉为经典.本文所谈的所谓架构二字,核心即是对于对于富客户端的 代码组织/职责划分 .纵览这十年内的架构模式变迁 ...
- Microservice架构模式简介
在2014年,Sam Newman,Martin Fowler在ThoughtWorks的一位同事,出版了一本新书<Building Microservices>.该书描述了如何按照Mic ...
随机推荐
- mysql 删除表记录 delete和truncate table区别
MySQL中删除表记录delete from和truncate table的用法区别: mysql中有两种删除表中记录的方法: (1)delete from语句, (2)truncate table语 ...
- Number Sequence HDU - 5014
There is a special number sequence which has n+1 integers. For each number in sequence, we have two ...
- BZOJ 1982 [Spoj 2021]Moving Pebbles(博弈论)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1982 [题目大意] 两个人玩游戏. 每次任选一堆,首先拿掉至少一个石头, 然后移动任意 ...
- BZOJ 2342 [Shoi2011]双倍回文(manacher+并查集)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2342 [题目大意] 记Wr为W串的倒置,求最长的形如WWrWWr的串的长度. [题解] ...
- 【强连通分量缩点】【DFS】【动态规划】Urozero Autumn Training Camp 2016 Day 5: NWERC-2016 Problem B. British Menu
有向图,不经过重复点的最长链,强连通分量大小不超过5. 每个强连通分量内部暴力预处理任意两对点之间的最长路,外面DAG上dp. 不是很好写,但是预处理完了之后,可以重构每个强连通分量内部的结构,然后整 ...
- 【动态规划】【滚动数组】【搜索】Playrix Codescapes Cup (Codeforces Round #413, rated, Div. 1 + Div. 2) D. Field expansion
显然将扩张按从大到小排序之后,只有不超过前34个有效. d[i][j]表示使用前i个扩张,当length为j时,所能得到的最大的width是多少. 然后用二重循环更新即可, d[i][j*A[i]]= ...
- bzoj 2468: [中山市选2010]三核苷酸
2468: [中山市选2010]三核苷酸 Description 三核苷酸是组成DNA序列的基本片段.具体来说,核苷酸一共有4种,分别用’A’,’G’,’C’,’T’来表示.而三核苷酸就是由3个核苷酸 ...
- [百度之星2014资格赛] Disk Schedule 报告
Disk Schedule Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) To ...
- ES6 函数参数的默认值
基本用法 在ES6之前,不能直接为函数的参数指定默认值,只能采取变通的方法. function log(x,y){ y = y||'world'; console.log(x,y); } log('k ...
- 配置友盟最新SDK遇到的问题
编译报错 Undefined symbols for architecture i386:原因:i386是代表模拟器,显示i386错误说明静态库不支持模拟器,只支持真机.友盟最新SDK可能不支持模拟 ...