iOS ViewController 瘦身实践

当我们每次重复性的在含有 tableView 的 ViewController 里面写 table view delegate 和 dataSource方法时,我们是否感到厌烦呢?出于尽量不做重复的事情的目的,我们是否可以把 tableView 代理方法抽取出一个公共类呢?答案当然是肯定的。

在沐风影音项目中,我将 table view dataSource 方法抽取出来,使用 ArrayDataSource 类进行统一管理。当一个 table view 中展示的是一个个对象,我们都可以使用这种方式。这样开始费一点时间,后来会节省很多时间,所谓磨刀不误砍柴工是也。

核心代码如下:

1. 公共类 ArrayDataSource

ArrayDataSource.h

1
2
3
4
5
6
7
8
9
10
11
12
13
#import <Foundation/Foundation.h>

typedef void (^TableViewCellConfigureBlock)(id cell, id item);

@interface ArrayDataSource : NSObject<UITableViewDataSource>

- (id)initWithItems:(NSArray *)anItems
cellIdentifier:(NSString *)aCellIdentifier
configureCellBlock:(TableViewCellConfigureBlock)aConfigureCellBlock;

- (id)itemAtIndexPath:(NSIndexPath *)indexPath;

@end

ArrayDataSource.m

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#import "ArrayDataSource.h"

@interface ArrayDataSource ()

@property (nonatomic, strong) NSArray *items;
@property (nonatomic, copy) NSString *cellIdentifier;
@property (nonatomic, copy) TableViewCellConfigureBlock configureCellBlock;

@end

@implementation ArrayDataSource

- (id)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 copy];// 在初始化 cell 的时候赋值 configureCellBlock
}
return self;
}

- (id)itemAtIndexPath:(NSIndexPath *)indexPath
{
return self.items[(NSUInteger) indexPath.row];
}


#pragma mark 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
forIndexPath:indexPath];
id item = [self itemAtIndexPath:indexPath];
self.configureCellBlock(cell, item);// 这里执行block方法,为cell元素赋值
return cell;
}

@end
沐风影音中使用的对象 MFFolder,当然你可以根据自己需要定义不同的模型,之后只要将 model 类传递给cell 就好了。

模型类 MFFolder.h

1
2
3
4
5
6
7
8
9
#import <Foundation/Foundation.h>

@interface MFFolder : NSObject

@property(nonatomic,strong) NSString *name;// 文件夹名称
@property(nonatomic,strong) NSString *imgName;// 缩略图名称
@property(nonatomic,strong) NSArray * subItems;// 子对象

@end

自定义cell MFFolderTableViewCell.h

1
2
3
4
5
6
7
8
9
10
11
12
13
#import <UIKit/UIKit.h>

@class MFFolder;

@interface MFFolderTableViewCell : UITableViewCell

@property (weak, nonatomic) IBOutlet UIImageView *imgVIew;
@property (weak, nonatomic) IBOutlet UILabel *nameLbl;

// 根据 MFFolder 配置 cell 内容
- (void)configureForFolder:(MFFolder *)folder;

@end

MFFolderTableViewCell.m

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#import "MFFolderTableViewCell.h"
#import "MFFolder.h"

@implementation MFFolderTableViewCell

- (void)awakeFromNib {
[super awakeFromNib];
// Initialization code
}

- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];

// Configure the view for the selected state
}

/*
-(id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{
self = [super initWithStyle: style reuseIdentifier:reuseIdentifier];
if (self) {
NSArray *nibArray = [[NSBundle mainBundle]loadNibNamed:@"MFFolderTableViewCell" owner:nil options:nil];
self = [nibArray lastObject];
}
return self;
}*/

- (void)configureForFolder:(MFFolder *)folder
{
self.imgVIew.image = [UIImage imageNamed:folder.imgName];
self.nameLbl.text = folder.name;

self.nameLbl.numberOfLines = 0;
self.nameLbl.minimumScaleFactor = 0.6;
self.nameLbl.adjustsFontSizeToFitWidth = YES;
}


@end
3. viewController 移动文件页面,一个viewController示例

MFFolderViewController.m

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#import "MFFolderViewController.h"
#import "ArrayDataSource.h"
#import "MFFolder.h"
#import "MFFolderTableViewCell.h"
#import "MFFileManager.h"
#import "MFFileTypeJudgmentUtil.h"

static NSString * const FolderCellIdentifier = @"FolderCell";

@interface MFFolderViewController ()

@property (weak, nonatomic) IBOutlet UITableView *myTableView;
@property (nonatomic, strong) ArrayDataSource * foldersArrayDataSource;
@property (nonatomic, strong) NSMutableArray *folders;// 当前页面含有的文件夹数组

@end

@implementation MFFolderViewController

- (void)viewDidLoad {
[super viewDidLoad];

self.title = @"移动文件";

// 初始化数据源
[self loadDataArray];
// 设置tableView
[self setupTableView];
}

- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];

}

// 设置tableView
- (void)setupTableView
{
TableViewCellConfigureBlock configureCell = ^(MFFolderTableViewCell *cell, MFFolder *folder) {
[cell configureForFolder:folder];
};// 这里初始化 cellConfigureBlock
NSArray *items = [self.folders copy];

// 对比指针地址
NSLog(@"items== %p",items);
NSLog(@"self.folders== %p",self.folders);

self.foldersArrayDataSource = [[ArrayDataSource alloc] initWithItems:items
cellIdentifier:FolderCellIdentifier
configureCellBlock:configureCell];
self.myTableView.dataSource = self.foldersArrayDataSource;
// 如果使用 registerClass,需要在cell的实现文件中重写initWithStyle并加载自己的nib
// [self.myTableView registerClass:[MFFolderTableViewCell class] forCellReuseIdentifier:FolderCellIdentifier];
[self.myTableView registerNib:[UINib nibWithNibName:@"MFFolderTableViewCell" bundle:nil] forCellReuseIdentifier:FolderCellIdentifier];
}

#pragma mark UITableViewDelegate

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{

}


#pragma mark - Custom Methods
#pragma mark - 加载数据源
-(void)loadDataArray {
NSMutableArray * filesArr = [MFFileManager readDownloadedFiles:@""];
self.folders = [[NSMutableArray alloc] init];

for (NSString *name in filesArr) {
if ([MFFileTypeJudgmentUtil isFolderType:name]) {// 判断是否是文件夹

MFFolder *folder = [[MFFolder alloc] init];
folder.name = name;
folder.imgName = @"cellThumbnailFolder";

[self.folders addObject:folder];
}
}

}
@end

至此,一个简单的 tableView 瘦身示例完毕。

2018.02.05
上海 虹桥

Joey Chang wechat
扫描二维码,关注我的公众号
坚持原创技术分享,您的支持将鼓励我继续创作!