一个架构合理的UITableView应该是怎样的
1个回答
展开全部
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。新建一个工程,DemoTableView修改ViewController.m,给当前视图加入一个UITabelView。
view sourceprint?
01.#import "ViewController.h"
02.
03.@interface ViewController () <UITableViewDataSource, UITableViewDelegate>
04.
05.@property (strong, nonatomic) UITableView *tableView;
06.
07.@end
08.
09.@implementation ViewController
10.
11.- (void)viewDidLoad {
12.[super viewDidLoad];
13.// Do any additional setup after loading the view, typically from a nib.
14.
15._tableView = [[UITableView alloc] initWithFrame:self.view.bounds];
16._tableView.dataSource = self;
17._tableView.delegate = self;
18.[self.view addSubview:self.tableView];
19.
20.}
21.
22.@end
如果我们现在尝试运行,肯定是出错的,因为我们没有实现DataSource和Delegate。在实现DataSource之前,让我们先准备号数据源Model。
2.1 Model
新建一个Model类:DemoObject。它有两个属性title 和 content。
view sourceprint?
01.//
02.// DemoObject.h
03.// DemoTableView
04.//
05.// Created by xiazhidi on 15/3/12.
06.//
07.
08.#import <Foundation/Foundation.h>
09.
10.@interface DemoObject : NSObject
11.
12.@property (strong, nonatomic) NSString *title;
13.@property (strong, nonatomic) NSString *content;
14.
15.@end
Model层做到这里就完毕了,Model的获取,修改什么的都一股脑丢到ViewController里甚至TableView的DateSoucre里进行。但是合理的架构应该是这样的,我们应该在Model层封装好所有的数据请求和处理逻辑,而只暴露出获取的接口提供给Controller层使用。我们新建一个Category : DemoObject+Api。在这当中封装好Model的获取和处理逻辑。
view sourceprint?
01.//
02.// DemoObject+Api.h
03.// DemoTableView
04.//
05.// Created by xiazhidi on 15/3/12.
06.// Copyright (c) 2015年 baixing. All rights reserved.
07.//
08.
09.#import "DemoObject.h"
10.
11.typedef void(^DemoObjectFetchCompletionBlock)(NSArray *demoObjects, NSError *error);
12.
13.@interface DemoObject (Api)
14.
15.+ (void)fetchWithCompletionBlock:(DemoObjectFetchCompletionBlock)completionBlock;
16.
17.@end
可以看到,我们提供了一个类方法暴露给Controller层,让它可以方便的获取数据,数据通过Block返回,当然你也可以用Delegate实现,这个看个人习惯。相应的,.m的实现如下:(我们只是造一些假数据,真实应用中肯定要设计从网络获取)
view sourceprint?
01.//
02.// DemoObject+Api.m
03.// DemoTableView
04.//
05.// Created by xiazhidi on 15/3/12.
06.// Copyright (c) 2015年 baixing. All rights reserved.
07.//
08.
09.#import "DemoObject+Api.h"
10.
11.@implementation DemoObject (Api)
12.
13.+ (void)fetchWithCompletionBlock:(DemoObjectFetchCompletionBlock)completionBlock
14.{
15.NSMutableArray *mArray = [[NSMutableArray alloc] initWithCapacity:10];
16.
17.for (NSInteger i = 0; i < 10; i++)
18.{
19.DemoObject *demoObject = [[DemoObject alloc] init];
20.demoObject.title = [NSString stringWithFormat:@"这是第%lu个标题", (unsigned long)i];
21.demoObject.content = [NSString stringWithFormat:@"这是第%lu个内容", (unsigned long)i];
22.[mArray addObject:demoObject];
23.}
24.
25.if (completionBlock)
26.{
27.completionBlock([mArray copy], nil);
28.}
29.}
30.
31.@end
2.2 View
对于UITableView的View层来说,就是我们要建立一个 Cell ,可以用Xib也可以不用。那我们这里就用吧,毕竟正式项目中,autolayout什么的用起来还是方便的。新建DemoTableViewCell,放好两个label,连连线什么的就不讲了。具体可看后面附的源码。关键是,我们需要在cell中,实现cell的配置逻辑。所以我们建立了一个category
view sourceprint?
01.//
02.// DemoTableViewCell+Configure.h
03.// DemoTableView
04.//
05.// Created by xiazhidi on 15/3/12.
06.// Copyright (c) 2015年 baixing. All rights reserved.
07.//
08.
09.#import "DemoTableViewCell.h"
10.@class DemoObject;
11.
12.@interface DemoTableViewCell (Configure)
13.
14.- (void)configureWithDemoObject:(DemoObject *)demoObject;
15.
16.@end
view sourceprint?
01.// DemoTableViewCell+Configure.m
02.// DemoTableView
03.//
04.// Created by xiazhidi on 15/3/12.
05.// Copyright (c) 2015年 baixing. All rights reserved.
06.//
07.
08.#import "DemoTableViewCell+Configure.h"
09.#import "DemoObject.h"
10.
11.@implementation DemoTableViewCell (Configure)
12.
13.- (void)configureWithDemoObject:(DemoObject *)demoObject
14.{
15.self.titleLabel.text = demoObject.title;
16.self.contentLabel.text = demoObject.content;
17.}
18.
19.@end
暴露了一个接口给Controller来实现view的配置。 这样的优点是,Controller层不会堆积很多的代码让人头痛(想想一个复杂的cell可能会有多少需要配置的UI元素),并且会很方便的方便Cell的复用。
2.3 Controller
我们再来看看现在Controller层具体实现的代码,层次会十分清晰。
view sourceprint?
01.//
02.// ViewController.m
03.// DemoTableView
04.//
05.// Created by xiazhidi on 15/3/12.
06.// Copyright (c) 2015年 baixing. All rights reserved.
07.//
08.
09.#import "ViewController.h"
10.#import "DemoObject+Api.h"
11.#import "DemoTableViewCell+Configure.h"
12.
13.@interface ViewController () <UITableViewDataSource, UITableViewDelegate>
14.
15.@property (strong, nonatomic) UITableView *tableView;
16.
17.@property (strong, nonatomic) NSArray *demos;
18.
19.@end
20.
21.@implementation ViewController
22.
23.- (void)viewDidLoad {
24.[super viewDidLoad];
25.// Do any additional setup after loading the view, typically from a nib.
26.
27._tableView = [[UITableView alloc] initWithFrame:self.view.bounds];
28._tableView.dataSource = self;
29._tableView.delegate = self;
30.[_tableView registerNib:[UINib nibWithNibName:@"DemoTableViewCell" bundle:nil] forCellReuseIdentifier:DemoTableViewCellReuseIdentifier];
31.[self.view addSubview:self.tableView];
32.
33.__weak ViewController *weakSelf = (ViewController *)self;
34.
35.[DemoObject fetchWithCompletionBlock:^(NSArray *demoObjects, NSError *error) {
36.if (!error)
37.{
38.weakSelf.demos = demoObjects;
39.[weakSelf.tableView reloadData];
40.}
41.}];
42.}
43.
44.#pragma mark - UITableViewDataSource
45.
46.- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
47.{
48.return self.demos.count;
49.}
50.
51.- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
52.{
53.return 60.0f;
54.}
55.
56.- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
57.{
58.DemoTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:DemoTableViewCellReuseIdentifier forIndexPath:indexPath];
59.
60.[cell configureWithDemoObject:self.demos[indexPath.row]];
61.
62.return cell;
63.}
64.
65.@end
三、总结
以上是一个简单的UITableView的小例子,其实这样做的目的,就是为了给Controller瘦身,让代码逻辑更清晰,让结构更合理。另外还有一些优化的空间,比如把DateSource独立出来成为一个类,这样在Controller当中不在出现DateSource的代码,会更加清爽,但是个人喜好,我不是很喜欢这样做。
一、MVC
首先我们要谈论的是MVC,这并不奇怪,iOS开发整个的架构体系,就是一个经典的MVC, Model层负责数据,View层负责展现,Controller层负责协调和处理。而不论你使用UITableViewController 还是 UIViewController中有一个UITableView,你的UITableView 的 DataSource 的几个方法,都应该起到一个Controller的作用,而不应该在当中进行Model层数据的处理,或者View层视图的修改。
二、改怎么做
空洞的话说完了,怎么做呢?我们就从头开始实现一个UITableView。新建一个工程,DemoTableView修改ViewController.m,给当前视图加入一个UITabelView。
view sourceprint?
01.#import "ViewController.h"
02.
03.@interface ViewController () <UITableViewDataSource, UITableViewDelegate>
04.
05.@property (strong, nonatomic) UITableView *tableView;
06.
07.@end
08.
09.@implementation ViewController
10.
11.- (void)viewDidLoad {
12.[super viewDidLoad];
13.// Do any additional setup after loading the view, typically from a nib.
14.
15._tableView = [[UITableView alloc] initWithFrame:self.view.bounds];
16._tableView.dataSource = self;
17._tableView.delegate = self;
18.[self.view addSubview:self.tableView];
19.
20.}
21.
22.@end
如果我们现在尝试运行,肯定是出错的,因为我们没有实现DataSource和Delegate。在实现DataSource之前,让我们先准备号数据源Model。
2.1 Model
新建一个Model类:DemoObject。它有两个属性title 和 content。
view sourceprint?
01.//
02.// DemoObject.h
03.// DemoTableView
04.//
05.// Created by xiazhidi on 15/3/12.
06.//
07.
08.#import <Foundation/Foundation.h>
09.
10.@interface DemoObject : NSObject
11.
12.@property (strong, nonatomic) NSString *title;
13.@property (strong, nonatomic) NSString *content;
14.
15.@end
Model层做到这里就完毕了,Model的获取,修改什么的都一股脑丢到ViewController里甚至TableView的DateSoucre里进行。但是合理的架构应该是这样的,我们应该在Model层封装好所有的数据请求和处理逻辑,而只暴露出获取的接口提供给Controller层使用。我们新建一个Category : DemoObject+Api。在这当中封装好Model的获取和处理逻辑。
view sourceprint?
01.//
02.// DemoObject+Api.h
03.// DemoTableView
04.//
05.// Created by xiazhidi on 15/3/12.
06.// Copyright (c) 2015年 baixing. All rights reserved.
07.//
08.
09.#import "DemoObject.h"
10.
11.typedef void(^DemoObjectFetchCompletionBlock)(NSArray *demoObjects, NSError *error);
12.
13.@interface DemoObject (Api)
14.
15.+ (void)fetchWithCompletionBlock:(DemoObjectFetchCompletionBlock)completionBlock;
16.
17.@end
可以看到,我们提供了一个类方法暴露给Controller层,让它可以方便的获取数据,数据通过Block返回,当然你也可以用Delegate实现,这个看个人习惯。相应的,.m的实现如下:(我们只是造一些假数据,真实应用中肯定要设计从网络获取)
view sourceprint?
01.//
02.// DemoObject+Api.m
03.// DemoTableView
04.//
05.// Created by xiazhidi on 15/3/12.
06.// Copyright (c) 2015年 baixing. All rights reserved.
07.//
08.
09.#import "DemoObject+Api.h"
10.
11.@implementation DemoObject (Api)
12.
13.+ (void)fetchWithCompletionBlock:(DemoObjectFetchCompletionBlock)completionBlock
14.{
15.NSMutableArray *mArray = [[NSMutableArray alloc] initWithCapacity:10];
16.
17.for (NSInteger i = 0; i < 10; i++)
18.{
19.DemoObject *demoObject = [[DemoObject alloc] init];
20.demoObject.title = [NSString stringWithFormat:@"这是第%lu个标题", (unsigned long)i];
21.demoObject.content = [NSString stringWithFormat:@"这是第%lu个内容", (unsigned long)i];
22.[mArray addObject:demoObject];
23.}
24.
25.if (completionBlock)
26.{
27.completionBlock([mArray copy], nil);
28.}
29.}
30.
31.@end
2.2 View
对于UITableView的View层来说,就是我们要建立一个 Cell ,可以用Xib也可以不用。那我们这里就用吧,毕竟正式项目中,autolayout什么的用起来还是方便的。新建DemoTableViewCell,放好两个label,连连线什么的就不讲了。具体可看后面附的源码。关键是,我们需要在cell中,实现cell的配置逻辑。所以我们建立了一个category
view sourceprint?
01.//
02.// DemoTableViewCell+Configure.h
03.// DemoTableView
04.//
05.// Created by xiazhidi on 15/3/12.
06.// Copyright (c) 2015年 baixing. All rights reserved.
07.//
08.
09.#import "DemoTableViewCell.h"
10.@class DemoObject;
11.
12.@interface DemoTableViewCell (Configure)
13.
14.- (void)configureWithDemoObject:(DemoObject *)demoObject;
15.
16.@end
view sourceprint?
01.// DemoTableViewCell+Configure.m
02.// DemoTableView
03.//
04.// Created by xiazhidi on 15/3/12.
05.// Copyright (c) 2015年 baixing. All rights reserved.
06.//
07.
08.#import "DemoTableViewCell+Configure.h"
09.#import "DemoObject.h"
10.
11.@implementation DemoTableViewCell (Configure)
12.
13.- (void)configureWithDemoObject:(DemoObject *)demoObject
14.{
15.self.titleLabel.text = demoObject.title;
16.self.contentLabel.text = demoObject.content;
17.}
18.
19.@end
暴露了一个接口给Controller来实现view的配置。 这样的优点是,Controller层不会堆积很多的代码让人头痛(想想一个复杂的cell可能会有多少需要配置的UI元素),并且会很方便的方便Cell的复用。
2.3 Controller
我们再来看看现在Controller层具体实现的代码,层次会十分清晰。
view sourceprint?
01.//
02.// ViewController.m
03.// DemoTableView
04.//
05.// Created by xiazhidi on 15/3/12.
06.// Copyright (c) 2015年 baixing. All rights reserved.
07.//
08.
09.#import "ViewController.h"
10.#import "DemoObject+Api.h"
11.#import "DemoTableViewCell+Configure.h"
12.
13.@interface ViewController () <UITableViewDataSource, UITableViewDelegate>
14.
15.@property (strong, nonatomic) UITableView *tableView;
16.
17.@property (strong, nonatomic) NSArray *demos;
18.
19.@end
20.
21.@implementation ViewController
22.
23.- (void)viewDidLoad {
24.[super viewDidLoad];
25.// Do any additional setup after loading the view, typically from a nib.
26.
27._tableView = [[UITableView alloc] initWithFrame:self.view.bounds];
28._tableView.dataSource = self;
29._tableView.delegate = self;
30.[_tableView registerNib:[UINib nibWithNibName:@"DemoTableViewCell" bundle:nil] forCellReuseIdentifier:DemoTableViewCellReuseIdentifier];
31.[self.view addSubview:self.tableView];
32.
33.__weak ViewController *weakSelf = (ViewController *)self;
34.
35.[DemoObject fetchWithCompletionBlock:^(NSArray *demoObjects, NSError *error) {
36.if (!error)
37.{
38.weakSelf.demos = demoObjects;
39.[weakSelf.tableView reloadData];
40.}
41.}];
42.}
43.
44.#pragma mark - UITableViewDataSource
45.
46.- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
47.{
48.return self.demos.count;
49.}
50.
51.- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
52.{
53.return 60.0f;
54.}
55.
56.- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
57.{
58.DemoTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:DemoTableViewCellReuseIdentifier forIndexPath:indexPath];
59.
60.[cell configureWithDemoObject:self.demos[indexPath.row]];
61.
62.return cell;
63.}
64.
65.@end
三、总结
以上是一个简单的UITableView的小例子,其实这样做的目的,就是为了给Controller瘦身,让代码逻辑更清晰,让结构更合理。另外还有一些优化的空间,比如把DateSource独立出来成为一个类,这样在Controller当中不在出现DateSource的代码,会更加清爽,但是个人喜好,我不是很喜欢这样做。
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询