1. 程式人生 > 實用技巧 >如何修改一次程式碼就可以完成多種型別 cell 的 UITableView 增刪修改

如何修改一次程式碼就可以完成多種型別 cell 的 UITableView 增刪修改

前言

當一個 tableView 中的 cell 型別過多時,我們務必會在 tableView 的各個代理中做這樣那樣的判斷,當需要增加一種 cell,或調換 cell 的順序的時候我們就會在 tableView 的各個代理中進行修改判斷。
使用 ZBCellConfig 可以應對各種變態需求,當增刪、調換 cell 的順序時,只需一鍵配置。

簡介

  • ZBCellConfig 物件例項會將 tableView 中 cell 所需的基本資訊儲存下來,然後放到陣列中進行管理;
  • 每個 ZBCellConfig 例項與 tableView 中想要顯示的 cell 相對應。(但注意,是"想要顯示的"cell,由於 cell 的重用,實際上 cell 並不會生成那麼多);
  • 優點:改變不同型別 cell 的順序、增刪時,極為方便,只需改變用於存放 ZBCellConfig 的陣列即可,** 重點是無需在多個 tableView 代理方法中逐個修改 **。

結構

使用

  • 支援 cocoapods 匯入 pod 'ZBCellConfig'
  • 直接將檔案拖拽到專案中 #import "ZBCellConfig.h"

知識點


請下載示例專案檢視詳細使用方法及實際中如何使用 GitHub 下載地址
初、中、高、高 MVVM 內容上是一樣的,區別在於沒一級別知識點遞增。

基本使用

1 . 首先在控制器中宣告存放 ZBCellConfig 例項的二維陣列

/**
 * 二維陣列 (匹配 tableView 的資料結構,第一層是 section,第二層放 cell)
 */
@property (nonatomic, strong) NSMutableArray <NSArray <ZBCellConfig *> *> * cellConfigs;

2-1 . 初始化陣列,每一個 ZBCellConfig 為 cell 的基本資訊,改變不同型別 cell 的順序、增刪時,只需在此修改即可,無需在多個 tableView 代理方法中逐個修改(具體檢視 Demo 註釋很清晰)

-  (NSMutableArray<NSArray<ZBCellConfig *> *> *)cellConfigs {
    _cellConfigs = [[NSMutableArray alloc] init];
    // cell1
    ZBCellConfig *cell1Config = [ZBCellConfig cellConfigWithClass:[LowTableViewCell1 class] showCellInfoMethod:@selector(setModel:)];
    [_cellConfigs addObject:@[cell1Config]];
    // cell2
    ZBCellConfig *cell2Config = [ZBCellConfig cellConfigWithClass:[LowTableViewCell1 class] showCellInfoMethod:@selector(setModel:)];
    [_cellConfigs addObject:@[cell2Config]];
    // cell3
    ....
    return _cellConfigs;
}

2-2 . 增刪只需這樣:

3 . tableView 代理中實現部分

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return self.cellConfigs.count;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return [self.cellConfigs[section] count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    // 根據 indexPath 獲取 對應的 cellConfig
    ZBCellConfig *cellConfig = self.cellConfigs[indexPath.section][indexPath.row];
    // 根據對應的 cellConfig 獲取 cell,並給 cell 賦值 根據模型顯示。
    // • dataModels: 這裡由於為示例程式碼不是用真實資料,只起到 執行 cell 的賦值函式。在實際專案中應該傳遞從網路請求的真實資料。
    UITableViewCell *cell = [cellConfig cellOfCellConfigWithTableView:tableView dataModels:@[[LowModel new]]];

    return cell;
}

cell 自適應高度

1 . tableView 設定如下

/**
 * default is 0, which means there is no estimate
 * estimatedRowHeight 預設為 0,不估算cell高度
 * 賦值不為 0 時候,開啟cell估值配合 layout 約束,進行cell高度自適應
 * 也就是說想要自動佈局 cell 高度就給這個 estimatedRowHeight 屬性賦值,值為你所有 cell 的平均高度的一個估值
 */
_heightTableView.estimatedRowHeight = 100;
 // iOS8 系統中 rowHeight 的預設值已經設定成了 UITableViewAutomaticDimension
_heightTableView.rowHeight = UITableViewAutomaticDimension;

2 . cell 需採用 AutoLayout 佈局,masory 或 xib 託線的形式皆可,約束規定上左下右還有讓 cell 知道內容的高:

tableView style

  1. UITableViewStylePlain 和 UITableViewStyleGrouped 區別
  2. UITableViewStylePlain:sectionView 當 tableView cectionHeader/Footer 會預設高度為 0, 滑動到頂部時 會停留到導航欄底部
  3. UITableViewStyleGrouped:sectionView 當 tableView cectionHeader/Footer 會預設高度為 10, 滑動到頂部時 不會停留到導航欄底部
  4. 注意:當需要 為 UITableViewStyleGrouped 時檢視【MediaExample 使用示例】

ZBCellConfig

通過函式 - (void)zb_performSelector:(SEL)aSelector withObjects:(NSArray *)objects來執行 初始化時配置好的showCellInfoMethod
此函式是對 - (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2;的一個擴充套件,以陣列的形式來傳遞多引數。
函式實現部分:

 // 簽名
NSMethodSignature *signature = [[self class] instanceMethodSignatureForSelector:aSelector];
if (signature == nil) {
    NSAssert(false, @"LINE=%d ERROR - 找不到 %@ 方法", __LINE__ ,NSStringFromSelector(aSelector));
}
// 包裝
NSInvocation *invocation  = [NSInvocation invocationWithMethodSignature:signature];
// 設定呼叫者
[invocation setTarget:self];
// 設定呼叫的方法 與 NSMethodSignature 簽名的方法一致
[invocation setSelector:aSelector];
// 0為target 1為_cmd 所以從2索引
for (int i = 0; i < (signature.numberOfArguments - 2); i++) {
    id dataModel = i < objects.count ? objects[i] : nil;
    [invocation setArgument:&dataModel atIndex:i+2];
}
// retain 所有引數,防止釋放
[invocation retainArguments];
[invocation invoke];

總結


把將要展示的幾種 cell 的基本資訊 以 tableView 的資料結構二維陣列的形式存放,儲存基本配置並不會生成多餘的 cell,內部建立採用 tableView 的重用機制。示例 Demo 中註釋詳細,Demo 下載地址


_ If I have no knife,I can't protect you.If I had a sword,I can't hold you.


如果我沒有刀,我就不能保護你。如果我有刀,我就不能擁抱你。


————《剪刀手愛德華》_