歡迎光臨
每天分享高質量文章

iOS–複數cell下優雅的程式碼結構

作者:kirito_song
連結:https://www.jianshu.com/p/723e8435586d

前言

最近換了新工作,第一個需求是寫幾個串列。

 

簡單的UITableView+Cell,但畢竟是入職後的第一個需求感覺要被review,所以還是想儘量弄得優雅一點。

需求

 

一個頁面,可能出現多種cell。

 

這個需求應該是很常見的,需要解決的問題是如何讓多個cell能夠共同響應同一個方法,這樣外部不需要知道具體的cell種類,只要呼叫同一個方法進行配置即可。

 

問了問朋友們大家基本上是兩派。

 

  • 協議

  • 基類

 

我個人以前也是用協議對多個cell進行約束的,透過讓cell遵循同一個協議並實現協議方法,讓外部達到統一配置的效果。

 

//cell共同遵循這個協議
@protocol ModuleACellConfigPropotol <NSObject>
- (void)configCellWithModel:(KTModel *)model;
@end


透過協議呼叫方法
UITableViewCell * cell= [tableView dequeueReusableCellWithIdentifier:cellID];
if ([cell respondsToSelector:@selector(configCellWithModel:)]) {
 [cell configCellWithModel:model];
}

對於基類繼承,大家普遍反映很噁心,準備重構,所以就不考慮了。

耦合

標準的MVC情況下, cell的配置方法,應該長這樣:

 

@interface KTTableViewCell00 : UITableViewCell
- (void)configShowViewWithTitle00:(NSString *)title;
@end

@interface KTTableViewCell01 : UITableViewCell
- (void)configShowViewWithTitle01:(NSString *)title;
@end

 

外部賦值也不應該把model傳遞給cell,而是隻傳遞cell指定的引數

 


[cell configShowViewWithTitle01:model.title];

 

而協議,為了達到統一配置,必須使用同一個方法進行約束。而cell們實際上的充要引數並不相同,所以只能將整個model作為引數進行傳遞。

 

@protocol ModuleACellConfigPropotol <NSObject>
- (void)configCellWithModel:(KTModel *)model;
@end

解耦

透過協議約束的方式,已經能夠成功實現統一配置。

但有一個問題隨之而來,這樣cell就與model產生了耦合,導致cell無法復用。

從結果上來看,這樣並不完美。

 

要解決這個問題,我覺得在cell與協議之間,又添加了一層配接器是個不錯的方案。

 
而這個配接器,我使用了Category進行實現。

 

補充一些:
需要註意Category使用過多,是會拖慢APP啟動時間的。所以除非特殊情況,不要把他當成cell於model解耦的標配。
但是這裡除了Category該怎麼做配接器,我目前沒什麼好的想法。

@interface KTTableViewCell00 (ModuleA) <ModuleACellConfigPropotol>

@end


@implementation KTTableViewCell00 (ModuleA)

- (void)configCellWithModel:(KTModel *)model {
 [self configShowViewWithTitle00:model.title];
}

@end

最後呼叫起來 :

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

    KTModel *model = self.dataArr[indexPath.row];

    NSString * cellID = model.identifier;
    UITableViewCell * cell= [tableView dequeueReusableCellWithIdentifier:cellID];

    if ([cell respondsToSelector:@selector(configCellWithModel:)]) {
        [cell configCellWithModel:model];
    }

    return cell;
}

結尾

人總是不斷成長的,這個方案目前是我覺得比較不錯的。

 

如果有大佬願意指教或者探討,不勝感激

 

 

Demo可以自取

 

後來的補充

  • 關於協議

我和很多朋友討論過,這是個比較成熟的解決方式。

  • 關於解耦

我個人在專案裡也不會把所有的cell和model全部解耦。
太執著於非必要的解耦,被條條框框限制死,也不好。

 

比如一個model有10個屬性,兩個cell使用這個model並且其中8個屬性公用。
我很可能會把model直接丟給cell,而不是每個cell單獨寫出一個方法來配置。

 

甚至,這兩個cell很有可能被我做成子類與父類的關係。比如這個:

 

 

他們真的太像了,第cell1和cell2甚至作為cell3和4的子類存在。
他們配置上的唯一區別就是使用紅點bool、紅點num還是不需要紅點。
我實在不願意把他們三個拆成三個方法

 

- (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;

 

  1. 這個cell被其他模組的復用的機率基本為0

  2. 這個Model離開了這個Cell也沒啥地方能用

 

SO…綁了就綁了唄…他倆本身就是共生的。

 

所以,解耦這一塊仁者見仁智者見智吧。

已同步到看一看
贊(0)

分享創造快樂