如何在一个类中实现两个拥有不同代理与数据源方法的TableView?
嘿,这个问题我之前帮不少iOS开发者捋清过思路——Objective-C确实不支持方法重载,但要在同一个类里搞定两个参数类型不同的TableView,咱们有好几招实用的办法:
解决同一个类中多TableView参数类型不同的问题
方法一:给TableView设置Tag区分
这是最常用的入门方案,先给两个TableView分别设置唯一的Tag值,然后在代理/数据源方法里通过判断Tag来分支处理不同参数类型的逻辑。
比如初始化TableView时:
// 第一个处理NSString类型数据的TableView UITableView *stringTableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 200)]; stringTableView.tag = 1001; stringTableView.dataSource = self; stringTableView.delegate = self; [self.view addSubview:stringTableView]; // 第二个处理NSNumber类型数据的TableView UITableView *numberTableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 220, self.view.frame.size.width, 200)]; numberTableView.tag = 1002; numberTableView.dataSource = self; numberTableView.delegate = self; [self.view addSubview:numberTableView];
然后在数据源方法里分支:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { if (tableView.tag == 1001) { return self.stringDataArray.count; // NSString类型数组 } else if (tableView.tag == 1002) { return self.numberDataArray.count; // NSNumber类型数组 } return 0; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { if (tableView.tag == 1001) { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"StringCell" forIndexPath:indexPath]; NSString *item = self.stringDataArray[indexPath.row]; cell.textLabel.text = item; return cell; } else if (tableView.tag == 1002) { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"NumberCell" forIndexPath:indexPath]; NSNumber *item = self.numberDataArray[indexPath.row]; cell.textLabel.text = [item stringValue]; return cell; } return [[UITableViewCell alloc] init]; }
方法二:直接判断TableView实例
如果你的两个TableView是类的属性,直接判断实例会比Tag更直观,避免Tag值冲突的问题。
先在类的头文件里声明属性:
@property (nonatomic, strong) UITableView *stringTableView; @property (nonatomic, strong) UITableView *numberTableView;
初始化时赋值:
self.stringTableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 200)]; self.stringTableView.dataSource = self; self.stringTableView.delegate = self; [self.view addSubview:self.stringTableView]; self.numberTableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 220, self.view.frame.size.width, 200)]; self.numberTableView.dataSource = self; self.numberTableView.delegate = self; [self.view addSubview:self.numberTableView];
然后在代理方法里判断实例:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { if (tableView == self.stringTableView) { // 处理NSString类型数据的逻辑 NSString *item = self.stringDataArray[indexPath.row]; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"StringCell" forIndexPath:indexPath]; cell.textLabel.text = item; return cell; } else if (tableView == self.numberTableView) { // 处理NSNumber类型数据的逻辑 NSNumber *item = self.numberDataArray[indexPath.row]; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"NumberCell" forIndexPath:indexPath]; cell.textLabel.text = [item stringValue]; return cell; } return [[UITableViewCell alloc] init]; }
方法三:给TableView绑定对应的数据模型(更优雅的方案)
如果不想写一堆判断分支,可以用Objective-C的关联对象,给每个TableView直接绑定对应的数据数组,这样在代理方法里直接取出数据,根据数据类型处理即可。
首先导入头文件:
#import <objc/runtime.h>
初始化TableView时绑定数据:
UITableView *stringTableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 200)]; stringTableView.dataSource = self; stringTableView.delegate = self; // 绑定字符串数组到TableView objc_setAssociatedObject(stringTableView, @selector(boundDataArray), self.stringDataArray, OBJC_ASSOCIATION_RETAIN_NONATOMIC); [self.view addSubview:stringTableView]; UITableView *numberTableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 220, self.view.frame.size.width, 200)]; numberTableView.dataSource = self; numberTableView.delegate = self; // 绑定数字数组到TableView objc_setAssociatedObject(numberTableView, @selector(boundDataArray), self.numberDataArray, OBJC_ASSOCIATION_RETAIN_NONATOMIC); [self.view addSubview:numberTableView];
然后在代理方法里取出数据处理:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { NSArray *dataArray = objc_getAssociatedObject(tableView, @selector(boundDataArray)); return dataArray.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { NSArray *dataArray = objc_getAssociatedObject(tableView, @selector(boundDataArray)); id item = dataArray[indexPath.row]; if ([item isKindOfClass:[NSString class]]) { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"StringCell" forIndexPath:indexPath]; cell.textLabel.text = item; return cell; } else if ([item isKindOfClass:[NSNumber class]]) { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"NumberCell" forIndexPath:indexPath]; cell.textLabel.text = [item stringValue]; return cell; } return [[UITableViewCell alloc] init]; }
小建议
- 如果只是两个简单的TableView,用Tag或者直接判断实例就足够简单高效;
- 如果后续可能扩展更多TableView,或者想让代码更解耦,绑定数据模型的方案会更优雅,不用修改代理方法里的判断逻辑。
内容的提问来源于stack exchange,提问作者Mehdi Negahban
相关产品推荐
相关产品推荐

