以前阅读了处理 iOS 中复杂的 Table Views 并保持优雅、iOS:如何构建具备多种 Cell 类型的表视图两篇译文,对于如何处理多类型cell的tableView有不小的收获。但我发现多类型cell的tableView之间也是有区别的。好比译文中就举例实现了动态多类型cell的tableView,这种状况使用MVVM模式有很好的效果。然而咱们开发过程当中也会有不少静态的多类型cell须要实现,好比微信的我的信息: json
- tableView: numberOfRowsInSection:
- tableView: cellForRowAtIndexPath:
- tableView: didSelectRowAtIndexPath:
复制代码
对于能躺着毫不坐着的我的习惯,我就想是否是能够改进下。数组
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;
}];
}
复制代码
以前我说使用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: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)
}
复制代码