先解釋下題目,好比下面這個設置頁面,裏面的內容會根據用戶身份、權限等等看到不一樣的可設置內容:3d
咱們先假設最簡單的狀況,形成左右兩邊差別的緣由徹底就是因爲一個變量的值的不一樣致使,isMyHome,若是爲YES,則最終看到左邊的效果,若是爲NO,則最終看到右邊的效果。代理
問題來了,你會如何實現UITableView的各類delegate?code
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { if (self.isMyHome) { return 3; } else { return 4; } } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { if (self.isMyHome) { // 有3個section switch (section) { case 0: return 4; break; case 1: return 1; break; case 2: return 2; break; default: break; } } else { switch (section) { case 0: return 2; break; case 1: return 1; break; case 2: return 1; break; case 3: return 1; break; default: break; } } return 0; } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { if (self.isMyHome) { if (indexPath.section == 2 && indexPath.row == 0) { // 有一個row稍微有點高 return 70; } else { return 40; } } else { return 40; } } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = ni; // ...真的不想寫了快吐了,這才一個變量的區別 return cell; }
以上的寫法有兩個大問題:blog
這才一個變量啊,試想實際項目中,每每不少變量綜合決定了哪一個row顯示、那個row不顯示、row長什麼樣。想一想下,若是有一天產品經理說,去掉「寶寶信息」這行,我以爲你就要瘋了,要把index所有都減一,每一個代理都要檢查一遍是否對得上index。ci
因此,這兩個問題,致使的後果:難實現、容易出bug、不易維護。產品
既然上面的實現這麼很差,該怎麼實現呢?其實就是逐一解決上面提到的兩個問題。it
對於1,其實形成問題的本質緣由是:在任什麼時候候,把一個row應該顯示與否、以及長什麼樣子、row對應的index是什麼, 這些問題都融合在一塊兒了,將問題複雜程度一下提高了不少。對於2,都使用枚舉就行了,避免
這裏提出解決辦法:io
這樣,「section、row的個數(index)」、「section、row是否顯示」、「row長什麼樣」,這三個問題就分散到了4個delegate中:table
代碼長這樣:變量
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 4; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { switch (section) { case SectionOne: return 4; break; case SectionTwo: return 1; break; case SectionThree: return 2; break; case SectionFour: return 1; break; default: break; } } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { if (indexPath.section == 0) { switch (indexPath.row) { case SectionOneRowOne: return 40 break; case SectionOneRowTwo: return self.isMyHome ? 40 : 0; break; case SectionOneRowThree: return self.isMyHome ? 40 : 0; break; case SectionOneRowFour: return 40 break; default: break; } } else if (indexPath.section == 1) { return 40; } else if (indexPath.section == 2) { switch (indexPath.row) { case SectionThreeRowOne: return self.isMyHome ? 70 : 0; break; case SectionThreeRowTwo: return 40; break; default: break; } } else { return self.isMyHome ? 0 : 40; } } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { // 對於每一個cell,配置內容就行了,index都是固定的 }
若是產品經理說,刪除「寶寶信息」這行吧,那麼咱們只要把heightForRowAtIndexPath,相應高度改成0就行了,以後產品經理反悔還能夠直接改回來,就算想徹底刪了,也很省事,不容易出bug。
核心思想,其實就是,UITableView的幾個delegate,分別只解決一個問題,不要把問題都揉在一塊兒,讓代碼變得複雜
假如要去掉一整個section怎麼辦,好比產品經理說,不要「我在小家的稱呼」這行了。
固然,沒問題,咱們直接把heightForRowAtIndexPath裏這行,改成0就行了嘛!
等等,雖然這行沒了,可是前兩個section之間的間隙,有可能會變大,由於只是設置了height爲0而已,seciton還在嘛。這種狀況怎麼辦?
不用擔憂,只要設置section的間隙,使用相似這種方式去設置,響應的改變section header的值,就行了~
其實,這種設置section的間隙的方式,也是咱們常用的嘛,基本都不太用系統默認的間隙。
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { return section == 0 ? 0 : 8; } - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { if (section == 0) { return [UIView new]; } UIView *sectionHeader = [[UIView alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, 8)]; sectionHeader.backgroundColor = [UIColor clearColor]; return sectionHeader; }