前言
最近換了新工作弄痹,第一個(gè)需求是寫(xiě)幾個(gè)列表肛真。
簡(jiǎn)單的UITableView+Cell蚓让,但畢竟是入職后的第一個(gè)需求感覺(jué)要被review历极,所以還是想盡量弄得優(yōu)雅一點(diǎn)趟卸。
需求
一個(gè)頁(yè)面衰腌,可能出現(xiàn)多種cell右蕊。
這個(gè)需求應(yīng)該是很常見(jiàn)的饶囚,需要解決的問(wèn)題是如何讓多個(gè)cell能夠共同響應(yīng)同一個(gè)方法萝风,這樣外部不需要知道具體的cell種類(lèi)睬塌,只要調(diào)用同一個(gè)方法進(jìn)行配置即可揩晴。
問(wèn)了問(wèn)朋友們大家基本上是兩派硫兰。
協(xié)議
基類(lèi)
我個(gè)人以前也是用協(xié)議對(duì)多個(gè)cell進(jìn)行約束的劫映,通過(guò)讓cell遵循同一個(gè)協(xié)議并實(shí)現(xiàn)協(xié)議方法泳赋,讓外部達(dá)到統(tǒng)一配置的效果。
//cell共同遵循這個(gè)協(xié)議
@protocol ModuleACellConfigPropotol <NSObject>
- (void)configCellWithModel:(KTModel *)model;
@end
?
?
通過(guò)協(xié)議調(diào)用方法
UITableViewCell<ModuleACellConfigPropotol> * cell= [tableView dequeueReusableCellWithIdentifier:cellID];
if ([cell respondsToSelector:@selector(configCellWithModel:)]) {
[cell configCellWithModel:model];
}
對(duì)于基類(lèi)繼承衅鹿,大家普遍反映很惡心大渤,準(zhǔn)備重構(gòu)泵三,所以就不考慮了俺抽。
耦合
標(biāo)準(zhǔn)的MVC情況下磷斧, cell的配置方法弛饭,應(yīng)該長(zhǎng)這樣:
@interface KTTableViewCell00 : UITableViewCell
- (void)configShowViewWithTitle00:(NSString *)title;
@end
?
@interface KTTableViewCell01 : UITableViewCell
- (void)configShowViewWithTitle01:(NSString *)title;
@end
外部賦值也不應(yīng)該把model傳遞給cell侣颂,而是只傳遞cell指定的參數(shù)
[cell configShowViewWithTitle01:model.title];
而協(xié)議憔晒,為了達(dá)到統(tǒng)一配置,必須使用同一個(gè)方法進(jìn)行約束。而cell們實(shí)際上的充要參數(shù)并不相同抚垄,所以只能將整個(gè)model作為參數(shù)進(jìn)行傳遞桐经。
@protocol ModuleACellConfigPropotol <NSObject>
- (void)configCellWithModel:(KTModel *)model;
@end
解耦
通過(guò)協(xié)議約束的方式,已經(jīng)能夠成功實(shí)現(xiàn)統(tǒng)一配置畔咧。
但有一個(gè)問(wèn)題隨之而來(lái)誓沸,這樣cell就與model產(chǎn)生了耦合宿百,導(dǎo)致cell無(wú)法復(fù)用垦页。
從結(jié)果上來(lái)看痊焊,這樣并不完美宋光。
要解決這個(gè)問(wèn)題,我覺(jué)得在cell與協(xié)議之間赘艳,又添加了一層適配器是個(gè)不錯(cuò)的方案。
而這個(gè)適配器掰曾,我使用了Category進(jìn)行實(shí)現(xiàn)旷坦。
補(bǔ)充一些:
需要注意Category使用過(guò)多,是會(huì)拖慢APP啟動(dòng)時(shí)間的捆蜀。所以除非特殊情況誊薄,不要把他當(dāng)成cell于model解耦的標(biāo)配。
但是這里除了Category該怎么做適配器咐刨,我目前沒(méi)什么好的想法。
@interface KTTableViewCell00 (ModuleA) <ModuleACellConfigPropotol>
?
@end
?
?
@implementation KTTableViewCell00 (ModuleA)
?
- (void)configCellWithModel:(KTModel *)model {
[self configShowViewWithTitle00:model.title];
}
?
@end
最后調(diào)用起來(lái) :
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
KTModel *model = self.dataArr[indexPath.row];
NSString * cellID = model.identifier;
UITableViewCell<ModuleACellConfigPropotol> * cell= [tableView dequeueReusableCellWithIdentifier:cellID];
if ([cell respondsToSelector:@selector(configCellWithModel:)]) {
[cell configCellWithModel:model];
}
return cell;
}
結(jié)尾
人總是不斷成長(zhǎng)的,這個(gè)方案目前是我覺(jué)得比較不錯(cuò)的沸久。
如果有大佬愿意指教或者探討,不勝感激
Demo可以自取
后來(lái)的補(bǔ)充
關(guān)于協(xié)議
我和很多朋友討論過(guò),這是個(gè)比較成熟的解決方式担钮。
關(guān)于解耦
我個(gè)人在項(xiàng)目里也不會(huì)把所有的cell和model全部解耦。
太執(zhí)著于非必要的解耦鲤嫡,被條條框框限制死,也不好。
比如一個(gè)model有10個(gè)屬性欺缘,兩個(gè)cell使用這個(gè)model并且其中8個(gè)屬性公用丧鸯。
我很可能會(huì)把model直接丟給cell丛肢,而不是每個(gè)cell單獨(dú)寫(xiě)出一個(gè)方法來(lái)配置。
甚至杠步,這兩個(gè)cell很有可能被我做成子類(lèi)與父類(lèi)的關(guān)系。比如這個(gè):
他們真的太像了,第cell1和cell2甚至作為cell3和4的子類(lèi)存在颠蕴。
他們配置上的唯一區(qū)別就是使用紅點(diǎn)bool
、紅點(diǎn)num
還是不需要紅點(diǎn)
寡键。
我實(shí)在不愿意把他們?nèi)齻€(gè)拆成三個(gè)方法
- (void)configcellWithTitle:(NSString *)title content:(NSString *)content dot:(BOOL)dot;
- (void)configcellWithTitle:(NSString *)title content:(NSString *)content dot:(NSString)num;
- (void)configcellWithTitle:(NSString *)title content:(NSString *)content;
- 這個(gè)cell被其他模塊的復(fù)用的幾率基本為0
- 這個(gè)Model離開(kāi)了這個(gè)Cell也沒(méi)啥地方能用
SO...綁了就綁了唄...他倆本身就是共生的。
所以,解耦這一塊仁者見(jiàn)仁智者見(jiàn)智吧。