一. 聲明:
在此文章中以tableView舉例, 便于描述.
二. 問題提出:
通常我們在寫一個tableView時候, 在其協(xié)議方法:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
在其中會創(chuàng)建多種cell或者從重用池中取出多種cell, 而通常使用index進行判斷, 什么時候用哪種cell, 如果這個頁面cell的種類少倒還好, 可是如果cell種類繁雜, 那么在這個協(xié)議方法中的判斷那真是非常折磨人的, 所以參照一些資料, 想出這個cell 的工廠模式.
三. 想法:
所謂的工廠模式, 咱們可以這么理解, 一個工廠就是一個加工車間, 如圖所示, 送進去原料, 在工廠中進行一系列加工處理, 然后生產(chǎn)出產(chǎn)品.
用在此處就體現(xiàn)出了面向?qū)ο蟮膬蓚€特性: 繼承和多態(tài). 我們用同樣的思維來思考cell工廠的模式, 我們需要原料, 送進CellFactory, 然后得到對應(yīng)種類的cell.
四. 思路:
同理, 通過數(shù)據(jù)轉(zhuǎn)化成Model, 再由tableViewCell呈現(xiàn)到界面給用戶(CollectionView同理).我們得知道自己需要什么, 當(dāng)然工廠的產(chǎn)品應(yīng)該是不同種類的cell, 那么他的原料也應(yīng)該是不一樣的, 那cell種類和什么東西是一一對應(yīng)的呢, 顯而易見是不同種類的model, 這樣我們基本的思路就成型了, 創(chuàng)建一個cellFactory, 放入Model, 進行處理, 生成cell
五. 實現(xiàn)過程:
- 第一步:創(chuàng)建基類BaseTableViewCell, 繼承于UITableViewCell,
在BaseTableViewCell.h中聲明方法:
// 賦值方法(在父類實現(xiàn), 在子類中重寫)
-(void)setModel:(__kindof BaseModel *)model;
在BaseTableViewCell.m中實現(xiàn)方法:
-(void)setModel:(__kindof BaseModel *)model {
}
- 第二步:創(chuàng)建model的基類BaseModel, 繼承于NSObject
在BaseModel.h中聲明方法
+(instancetype)modelWithDictionary:(NSDictionary *)dic;
在BaseModel.m中實現(xiàn)方法
-(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];
}
- 第三步:創(chuàng)建model: StudentModel, 繼承于BaseModel
//寫對應(yīng)的屬性, 此處為了簡單只寫了一個name
@property (nonatomic, copy) NSString *name;
- 第四步: 創(chuàng)建tableViewCell: StudentTableViewCell, 繼承于BaseTableViewCell
這里為了方便直接使用xib鋪了一個Label, 并重寫B(tài)aseTableView中的賦值方法:
-(void)setModel:(StudentModel *)model {
[super setModel:model];
_nameLabel.text = model.name;
}
- 第五步: 創(chuàng)建一個工廠類, LTQCellFactory
在LTQCellFactory.h中聲明:
+(BaseTableViewCell *)createTableViewCellWithModel:(BaseModel *)model
tableView:(UITableView *)tableView;
在LTQCellFactory.m中實現(xiàn):
+(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;
}
- 第六步:引入頭文件后,注冊Cell并在ViewController中實現(xiàn)
// 注冊StudentTableViewCell
[_tableView registerNib:[UINib nibWithNibName:@"StudentTableViewCell" bundle:[NSBundle mainBundle]] forCellReuseIdentifier:@"StudentTableViewCell"];
// 在tableView協(xié)議方法中實現(xiàn)
-(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進行關(guān)聯(lián)的, 所以在給model和cell的類起名字的時候, 一定要注意, model類名一定要為XXXModel, 而對應(yīng)的Cell名一定要為XXXTableViewCell或XXXCollectionViewCell,
而在注冊的時候直接用cell的類名作為cell在重用池中的重用標(biāo)識
例如:
結(jié)論: 這樣一來可以在這個dataSource的協(xié)議方法中可以節(jié)省大量的判斷和其他操作過程, 運用了繼承和多態(tài), 使得代碼更加整潔, 并且高大上了有木有, 如果有問題歡迎留言討論, 如果我寫的文章對你有幫助別忘記點個贊哦??