IOS多類型Cell的tableView實現

以前閱讀了處理 iOS 中複雜的 Table Views 並保持優雅iOS:如何構建具備多種 Cell 類型的表視圖兩篇譯文,對於如何處理多類型cell的tableView有不小的收穫。但我發現多類型cell的tableView之間也是有區別的。好比譯文中就舉例實現了動態多類型cell的tableView,這種狀況使用MVVM模式有很好的效果。然而咱們開發過程當中也會有不少靜態的多類型cell須要實現,好比微信的我的信息: json

這種風格的tableView內容基本是固定且簡單,若是要用MVVM去實現會比較繁瑣。或者像我以前我都是直接根據indexPath去一一對應生成,這在開發階段會很快很容易,可是後期若是要修改,好比增長一列或者刪除一列,這時候就須要同時修改下面代理中的代碼

- tableView: numberOfRowsInSection:
- tableView: cellForRowAtIndexPath:
- tableView: didSelectRowAtIndexPath:
複製代碼

對於能躺着毫不坐着的我的習慣,我就想是否是能夠改進下。數組

生成model

model的生成大同小異,基本是http獲取json後轉爲model。這裏我本身建立了json而後本地獲取模擬了下。bash

{
    "photo":"Audrey",
    "username":"奧黛麗",
    "userCode":"formyicarus222",
    "QRCode":"ico",
    "sex":1
}
複製代碼

model代碼:微信

@interface MultipeTypeModel : NSObject

@property (strong, nonatomic) NSString *photo;
@property (strong, nonatomic) NSString *username;
@property (strong, nonatomic) NSString *userCode;
@property (strong, nonatomic) NSString *qrCode;
@property (assign, nonatomic) NSInteger sex;

+ (void)requestForData:(void(^)(MultipeTypeModel *model))completion;
@end
複製代碼
- (instancetype)initWithDict:(NSDictionary *)dict
{
    self = [super init];
    if (self) {
        self.photo = dict[@"photo"];
        self.username = dict[@"username"];
        self.userCode = dict[@"userCode"];
        self.qrCode = dict[@"QRCode"];
    }
    return self;
}

+ (void)requestForData:(void (^)(MultipeTypeModel * _Nonnull))completion {
    NSString *path = [[NSBundle mainBundle] pathForResource:@"MultipleCell" ofType:@"json"];
    NSString *json= [[NSString alloc] initWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
    NSDictionary *jsonDict = [json jsonValueDecoded];
    MultipeTypeModel *model = [[MultipeTypeModel alloc] initWithDict:jsonDict];
    completion(model);
}
複製代碼

在vc裏調用post

- (void)geteData {
    [MultipeTypeModel requestForData:^(MultipeTypeModel * _Nonnull model) {
        self.muModel = model;
    }];
}
複製代碼

model生成數組

以前我說使用indexPath一一指定的方式去實現有個問題,就是後期須要增長或者刪除cell須要修改多處代碼。而解決這個問題的辦法就是將tableView的數據統一和一個數組關聯,那麼以後有需求變更,我只須要修改這個數組就能夠了。ui

model轉數組代碼:atom

- (NSArray *)tableArrayFromModel:(MultipeTypeModel *)model {
    NSArray *arr = @[
                     @[
                         @{
                             @"title":@"頭像",
                             @"image":model.photo?:@"",
                             @"type":@(MUTableCellTypeHeader),
                             @"selector":NSStringFromSelector(@selector(doHeaderPhotoAction:))
                             },
                         
                         @{
                             @"title":@"用戶名",
                             @"content":model.username?:@"",
                             @"type":@(MUTableCellTypeName),
                             @"selector":NSStringFromSelector(@selector(doUsernameAction:))
                             },
//                         
//                         @{
//                             @"title":@"性別",
//                             @"content":model.sex==1?@"男":@"女",
//                             @"type":@2
//                             },
                         
                         @{
                             @"title":@"微信號",
                             @"content":model.userCode?:@"",
                             @"type":@(MUTableCellTypeNameNoAccessory)
                             },
                         
                         @{
                             @"title":@"二維碼",
                             @"image":model.qrCode?:@"",
                             @"type":@(MUTableCellTypeHeader),
                             @"selector":NSStringFromSelector(@selector(doQRCodeAction:))
                             },
                         
                         @{
                             @"title":@"更多",
                             @"content":@"",
                             @"type":@(MUTableCellTypeName),
                             @"selector":NSStringFromSelector(@selector(doMoreAction:))
                             }
                         ],
                     
                     @[
                         @{
                             @"title":@"個人地址",
                             @"content":@"",
                             @"type":@(MUTableCellTypeName),
                             @"selector":NSStringFromSelector(@selector(doAddressAction:))
                             }
                         ]
                     
                     ];
    
    return arr;
}
複製代碼

這是一個二維數組,第一維表示section,第二維表示row。selector表示點擊cell的事件,type表示cell的類型。cell的類型我是建立一個枚舉來指定的:spa

typedef NS_ENUM(NSInteger,MUTableCellType) {
    MUTableCellTypeHeader=1,
    MUTableCellTypeName,
    MUTableCellTypeNameNoAccessory
};
複製代碼

通常來講這種tableView的數據是能夠修改的。我按以下思路修改:
1.直接修改self.muModel實例的屬性值。
2.從新將model轉爲數組
3.reloadData代理

- (void)reloadTableWithModel:(MultipeTypeModel *)model atIndexPath:(NSIndexPath *)indexPath {

    self.tableArray = [self tableArrayFromModel:model];
    if (indexPath) {
        [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
    }
    else {
        [self.tableView reloadData];
    }
}
複製代碼

tableView根據數組展現

到這裏,tableView相關數據就處理完,接下來就是將數據填充進tableView:code

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    NSArray *arr = self.tableArray[section];
    return arr.count;
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return self.tableArray.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    NSArray *sectionArr = self.tableArray[indexPath.section];
    NSDictionary *dict = sectionArr[indexPath.row];
    NSInteger type = [dict[@"type"] integerValue];
    switch (type) {
        case MUTableCellTypeHeader:
            {
                MUPhotoCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MUPhotoCell" forIndexPath:indexPath];
                cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
                [cell bindDict:dict];
                return cell;
            }
            break;
        case MUTableCellTypeName:
        {
            MUNameCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MUNameCell" forIndexPath:indexPath];
            cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
            [cell bindDict:dict];
            return cell;
        }
            break;
        case MUTableCellTypeNameNoAccessory:
        {
            MUNameCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MUNameCell" forIndexPath:indexPath];
            [cell bindDict:dict];
            return cell;
        }
            break;
            
        default:
            break;
    }
    
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell" forIndexPath:indexPath];
    cell.backgroundColor = [UIColor redColor];
    return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    [tableView deselectRowAtIndexPath:indexPath animated:true];
    
    NSArray *sectionArr = self.tableArray[indexPath.section];
    NSDictionary *dict = sectionArr[indexPath.row];
    NSString *selector = dict[@"selector"];
    SEL sel = NSSelectorFromString(selector);
    if ([self respondsToSelector:sel]) {
        [self performSelector:sel withObject:indexPath];
    }
}
複製代碼

這樣,當我後續接到需求變更,好比上面要添加一個cell,我只須要在- (NSArray *)tableArrayFromModel:(MultipeTypeModel *)model方法添加一個元素就能夠了。

@{
@"title":@"性別",
@"content":model.sex==1?@"男":@"女",
@"type":@(MUTableCellTypeName)
}

複製代碼
相關文章
相關標籤/搜索