专业知识分享(iOS)

iOS - TableViewCell(CollectionVi

2016-10-15  本文已影响487人  牵着螃蟹逛街走

一. 声明:
在此文章中以tableView举例, 便于描述.
二. 问题提出:
通常我们在写一个tableView时候, 在其协议方法:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;

在其中会创建多种cell或者从重用池中取出多种cell, 而通常使用index进行判断, 什么时候用哪种cell, 如果这个页面cell的种类少倒还好, 可是如果cell种类繁杂, 那么在这个协议方法中的判断那真是非常折磨人的, 所以参照一些资料, 想出这个cell 的工厂模式.
三. 想法:
所谓的工厂模式, 咱们可以这么理解, 一个工厂就是一个加工车间, 如图所示, 送进去原料, 在工厂中进行一系列加工处理, 然后生产出产品.

工厂模式.png

用在此处就体现出了面向对象的两个特性: 继承和多态. 我们用同样的思维来思考cell工厂的模式, 我们需要原料, 送进CellFactory, 然后得到对应种类的cell.
四. 思路:
同理, 通过数据转化成Model, 再由tableViewCell呈现到界面给用户(CollectionView同理).我们得知道自己需要什么, 当然工厂的产品应该是不同种类的cell, 那么他的原料也应该是不一样的, 那cell种类和什么东西是一一对应的呢, 显而易见是不同种类的model, 这样我们基本的思路就成型了, 创建一个cellFactory, 放入Model, 进行处理, 生成cell


CellFactory示意图.png

五. 实现过程:

  1. 第一步:创建基类BaseTableViewCell, 继承于UITableViewCell,
    在BaseTableViewCell.h中声明方法:
// 赋值方法(在父类实现, 在子类中重写)
-(void)setModel:(__kindof BaseModel *)model;

在BaseTableViewCell.m中实现方法:

-(void)setModel:(__kindof BaseModel *)model {
}
  1. 第二步:创建model的基类BaseModel, 继承于NSObject
    在BaseModel.h中声明方法
+(instancetype)modelWithDictionary:(NSDictionary *)dic;

在BaseModel.m中实现方法

-(void)setValue:(id)value forKey:(NSString *)key {
    [super setValue:value forKey:key];
}
-(void)setValue:(id)value forUndefinedKey:(NSString *)key {
    [super setValue:value forUndefinedKey:key];
}
-(id)valueForUndefinedKey:(NSString *)key {  
    return nil;
}
-(instancetype)initWithDictionary:(NSDictionary *)dic {
    self = [super init];
    if (self) {      
    [self setValuesForKeysWithDictionary:dic];
    }
    return self;
}
+(BaseModel *)modelWithDictionary:(NSDictionary *)dic {
    return [[self alloc] initWithDictionary:dic];
}
  1. 第三步:创建model: StudentModel, 继承于BaseModel
//写对应的属性, 此处为了简单只写了一个name
@property (nonatomic, copy) NSString *name;
  1. 第四步: 创建tableViewCell: StudentTableViewCell, 继承于BaseTableViewCell
    这里为了方便直接使用xib铺了一个Label, 并重写BaseTableView中的赋值方法:
-(void)setModel:(StudentModel *)model {
    [super setModel:model];
    _nameLabel.text = model.name;
}
StudentTableViewCell.png
  1. 第五步: 创建一个工厂类, LTQCellFactory
    在LTQCellFactory.h中声明:
+(BaseTableViewCell *)createTableViewCellWithModel:(BaseModel *)model
                                          tableView:(UITableView *)tableView;

在LTQCellFactory.m中实现:

+(BaseTableViewCell *)createTableViewCellWithModel:(BaseModel *)model
                                          tableView:(UITableView *)tableView {
    NSString *modelName = [NSString stringWithUTF8String:object_getClassName(model)];
    NSString *classNameOfCell = [[modelName substringToIndex:modelName.length - 5] stringByAppendingString:@"TableViewCell"];
    BaseTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:classNameOfCell];
    return cell;
}
  1. 第六步:引入头文件后,注册Cell并在ViewController中实现
// 注册StudentTableViewCell
 [_tableView registerNib:[UINib nibWithNibName:@"StudentTableViewCell" bundle:[NSBundle mainBundle]] forCellReuseIdentifier:@"StudentTableViewCell"];
// 在tableView协议方法中实现
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    BaseModel *model = _dataArr[indexPath.row];
    BaseTableViewCell *cell = [LTQCellFactory createTableViewCellWithModel:(BaseModel *)model tableView:tableView];
    [cell setModel:model];
    return cell;
}

补充: 由于我自己写的CellFactory是用model的Classname与Cell的Classname进行关联的, 所以在给model和cell的类起名字的时候, 一定要注意, model类名一定要为XXXModel, 而对应的Cell名一定要为XXXTableViewCell或XXXCollectionViewCell,
而在注册的时候直接用cell的类名作为cell在重用池中的重用标识
例如:


起名问题.png

结论: 这样一来可以在这个dataSource的协议方法中可以节省大量的判断和其他操作过程, 运用了继承和多态, 使得代码更加整洁, 并且高大上了有木有, 如果有问题欢迎留言讨论, 如果我写的文章对你有帮助别忘记点个赞哦😯

上一篇下一篇

猜你喜欢

热点阅读