iOS ViewController 瘦身实践

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

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

核心代码如下:

1. 公共类 ArrayDataSource

ArrayDataSource.h

#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

#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

#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

#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

#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

#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
上海 虹桥

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 前言 由于最近两个多月,笔者正和小伙伴们忙于对公司新项目的开发,笔者主要负责项目整体架构的搭建以及功能模块的分工。...
    CoderMikeHe阅读 27,237评论 74 270
  • 概述在iOS开发中UITableView可以说是使用最广泛的控件,我们平时使用的软件中到处都可以看到它的影子,类似...
    liudhkk阅读 9,118评论 3 38
  • 今天是中秋节,昨天晚上拖家带口的回家看妈妈。 上午在厨房忙活。之前十指不沾阳春水的我现在穿着围裙,在灶台前挥勺舞铲...
    夏花争妍阅读 190评论 0 0
  • 刚刚突然间还想再写一篇关于《龙纹身的女孩》之莉丝,之所以想写关于莉丝的解读,真的是因为刚刚在写上一篇文章的时候突然...
    三锦囊的猫阅读 427评论 0 2
  • 我回到了幼年的老家,还是熟悉的两层小楼,但显然周围的环境变了,父母那时候还年轻,在设定里,他们只有我一个女儿,我那...
    杨大离阅读 246评论 0 0