開頭:最近在利用有道的api嘗試作一個翻譯的應用,其中用到了tableview。有一段時間沒有接觸這個經常使用UI,發現該忘的都忘了哈哈。react
先貼上一張MVC的一張大圖(給本身看就好)api
controller 至關於媒介,幫助model和View創建其聯繫。道理我都懂,可是以往在coding的時候,每每會出現如下的狀況(代碼不看):-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
TeacherHomeworkListCell *cell = [tableView dequeueReusableCellWithIdentifier:@"TeacherHomeworkListCell" forIndexPath:indexPath];
cell.delegate = self;
NSArray *arr = homeworkListModelTDArray[indexPath.section];
cell.model = arr[indexPath.row];
if ([cell.model.requirements isEqualToString:@"0"]) {
cell.operateView.hidden = YES;
cell.correctHomeworkButton.hidden = YES;
cell.operateViewNR.hidden = NO;
} else {
cell.operateView.hidden = NO;
.......
複製代碼
貼上這麼多之前的代碼主要的,是能夠看出在以往coding過程當中,我又容易忽視了mvc的設計思想。這可能會致使:緩存
所以在此次coding 的過程當中,我時不時有意地注意到了這個問題,將全部的與UI展現有關的數據交由View下來處理,而避免在controller中直接的設置。因此此次個人設置數據源的方法圖片以下:bash
以往在設計一個tableView中有兩種以上不一樣cell時候,我容易在cellForRowAtIndexPath:這個方法中做出許許多多的if-else的判斷,而如今我將這個判斷交由cell本身來作,controller本身不須要知道cell是要什麼類型,而只要將獲得的cell展現便可。mvc
咱們須要作的,就是傳入須要的數據,能夠indexPath也能夠是model等。 這可能也很好的貫徹了「依賴注入」的設計原則。mvvm
同時,這可能對於後面的關於:自定義行高,一個tableView中有兩個cell等提供有益的幫助。ide
不過白貓黑貓,能抓到老鼠的的都是好貓哈哈哈。ui
這部分寫給本身看哈哈哈,主要是遇到了幾個忘記的知識點。spa
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
的方法,所以若是須要返回xib自定義的cell,則須要對這個方法override。在現現在的應用程序當中,一個tableView中含有多種類型的cell,這已經是一個廣泛的UI需求。翻譯
參考了網上各類方法以後,自我總結了一下。 我想到了以下兩種:
我在實現的過程當中,將view與xib綁定在一塊兒,根據傳入的indexPath或者數據,返回出指定類型的的cell。以往我會在xib文件中只放一個cell,而這次我則再也不是經過[array lastObject]取出惟一的cell,而是根據指定的index從多個cell中取出指定的cell。
附上僞碼:@implementation CustomCell
- (instancetype)cellWithIndexPath:(NSIndexPath *)indexPath {
CustomCell *cell = nil;
NSArray *cellArr = [[NSBundle mainBundle] loadNibWith...];
if (...){
cell = [cellArr objectAtIndex:index];
}else if (...) {
...
}else {
cell = [cellArr lastObject];
}
return cell;
}
@end
複製代碼
可是這種方法的缺點也很明顯,與tag的使用大同小異。當一個tableView須要許多種類型的cell來豐富內容的時候,採用這種方法在開發過程當中會帶來必定的混亂。
能夠適當的採用enum枚舉,但同時也要注意xib中左面板中視圖的上下位置。
例如上圖中,NormalTyepCell 的index=1,MeTypeCell爲2,而當二者調換了位置以後,索引也會發生改變。
我的也比較傾向於第二種方法,對於不一樣的類型的cell,應有不一樣的Identifier進行綁定,這樣子比較科學哈哈,同時採用了較爲高大上的MVVM,。
咱們大能夠像第一種方式同樣,從xib中取出所須要的cell,可是這也許就沒有多個Identifier存在的必要性。而針對不一樣標識符取出對應的cell,更多的是依賴:
[tableView dequeueReusableCellWithIdentifier:Identifier];
的調用。
一樣是能夠採用前面的方法來進行開發,可是細想一下,若是cell的類型過多,這樣子會致使view中代碼成本太高,相比與第一種方法,這種方法則更加麻煩。
如何解決?那就着手已產生的麻煩---胖View。
開始寫文章的時候並無考慮,可是寫着寫着就以爲也許能夠應用進來哈哈。9012但願能多寫文章,記錄筆記!
先貼幾張MVVM的大圖:
對於新面孔ViewModel:從MVC的controller中抽取出來的展現邏輯,負責從model中獲取view所需的數據,轉換成View能夠展現的數據,並暴露公開的屬性和命令供view進行綁定。
MVVM的採用能夠很好的爲view以及controller制定了瘦身的計劃,咱們將「獲取指定cell的Identifier」這一邏輯交由ViewModel來實現,而後經過controller告訴view須要哪一個cell。
附上viewModel和tableView設置數據源的僞碼:
@implementation ViewModel
- (NSString *)identifierWith:(Model *)model {
if (model.type == ?){
return firstCellID;
}else if (model ...){
return secondCellID;
}else {
return ...
}
}
@end
@implementation controller
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *identifier = [_viewModel identifierWith:model];
return [tableView dequeReusa....:identifier];
}
@end
複製代碼
在設置數據源方法中,我沒有進行cell爲空的操做處理,由於須要在這以前,對tableView進行全部類型cell的註冊,我的也比較喜歡先註冊cell的方式,這樣子可讓代碼看起來更加直觀。
結尾:
回顧前面所講的,個人出發點能夠理解爲始終是一個---爲controller制定瘦身計劃,同時使代碼更加容易維護。 以前只是一直想着coding,把功能實現就好,而歷來沒有想過將代碼寫在哪裏會更加合理。 固然上面的方法並非最佳😂,自我總結,僅供參考,大神路過有意見,還望指點下。
原本還想經過嘗試tableView自動算高來鞏固複習tableView,然而發現這裏是一塊肥肉,考慮篇幅,還得從新開一篇筆記細細評味😂。