我编写了一个示例代码,其中复合数据源包含每个部分的数据源对象。听起来很复杂,但实际上提供了一种易于扩展的架构。并保持您的视图控制器很小。
这种方法的优点:
- 小视图控制器
- ViewController 设置视图并处理用户交互——就像在 MVC 中一样
- 可重用的数据源
- 通过在每个部分使用不同的数据源,轻松自定义每个部分的单元格
基础数据源架构
这提供了简单的扩展并且易于重复使用。
@import UIKit;
@interface ComoundTableViewDataSource : NSObject
@property (nonatomic,strong, readonly) NSMutableDictionary *internalDictionary;
-(void) setDataSource:(id<UITableViewDataSource>)dataSource forSection:(NSUInteger)section;
-(instancetype)initWithTableView:(UITableView *)tableView;
@end
#import "ComoundTableViewDataSource.h"
@interface ComoundTableViewDataSource () <UITableViewDataSource>
@property (nonatomic,strong, readwrite) NSMutableDictionary *internalDictionary;
@property (nonatomic, weak) UITableView *tableView;
@end
@implementation ComoundTableViewDataSource
-(instancetype)initWithTableView:(UITableView *)tableView
{
self = [super init];
if (self) {
_tableView = tableView;
tableView.dataSource = self;
_internalDictionary = [@{} mutableCopy];
[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"Cell"];
}
return self;
}
-(void)setDataSource:(id<UITableViewDataSource>)dataSource forSection:(NSUInteger)section
{
self.internalDictionary[@(section)] = dataSource;
[self.tableView reloadData];
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [[self.internalDictionary allKeys] count];
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
id<UITableViewDataSource> sectionDataSource = self.internalDictionary[@(section)];
return [sectionDataSource tableView:tableView numberOfRowsInSection:section];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
id<UITableViewDataSource> sectionDataSource = self.internalDictionary[@(indexPath.section)];
return [sectionDataSource tableView:tableView cellForRowAtIndexPath:indexPath];
}
-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
id<UITableViewDataSource> sectionDataSource = self.internalDictionary[@(section)];
return [sectionDataSource tableView:tableView titleForHeaderInSection:section];
}
@end
@import UIKit;
@interface SingleSectionDataSource : NSObject <UITableViewDataSource>
@property (nonatomic, strong, readonly) NSArray *array;
@property (nonatomic, strong, readonly) UITableView *tableView;
- (instancetype)initWithArray:(NSArray *)array;
@end
#import "SingleSectionDataSource.h"
@interface SingleSectionDataSource ()
@property (nonatomic, strong, readwrite) NSArray *array;
@property (nonatomic, strong, readwrite) UITableView *tableView;
@end
@implementation SingleSectionDataSource
- (instancetype)initWithArray:(NSArray *)array
{
self = [super init];
if (self) {
self.array = array;
}
return self;
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
self.tableView = tableView;
return self.array.count;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
cell.textLabel.text = self.array[indexPath.row];
return cell;
}
-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
return [@(section) stringValue];
}
@end
选择数据源架构
我们从上面扩展类以允许每个部分选择一个
#import "ComoundTableViewDataSource.h"
@interface OnSelectionPerSectionComoundTableViewDataSource : ComoundTableViewDataSource
-(void)selectedCellAtIndexPath:(NSIndexPath *)indexPath;
@end
#import "OnSelectionPerSectionComoundTableViewDataSource.h"
#import "SingleSelectionSingleSectionDataSource.h"
@implementation OnSelectionPerSectionComoundTableViewDataSource
-(instancetype)initWithTableView:(UITableView *)tableView
{
self = [super initWithTableView:tableView];
if(self){
[tableView setAllowsMultipleSelection:YES];
}
return self;
}
-(void)selectedCellAtIndexPath:(NSIndexPath *)indexPath
{
SingleSelectionSingleSectionDataSource *sectionDataSource = self.internalDictionary[@(indexPath.section)];
[sectionDataSource selectedCellAtIndexPath:indexPath];
}
@end
查看控制器实现
正如所承诺的,一个非常纤薄的视图控制器:
@interface ViewController () <UITableViewDelegate>
@property (weak, nonatomic) IBOutlet UITableView *tableView;
@property (nonatomic, strong) OnSelectionPerSectionComoundTableViewDataSource *tableViewDataSource;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.tableViewDataSource = [[OnSelectionPerSectionComoundTableViewDataSource alloc] initWithTableView:self.tableView];
self.tableView.delegate = self;
[self.tableViewDataSource setDataSource:[[SingleSelectionSingleSectionDataSource alloc] initWithArray:@[@"Hallo", @"Welt"]] forSection:0];
[self.tableViewDataSource setDataSource:[[SingleSelectionSingleSectionDataSource alloc] initWithArray:@[@"Hello", @"World", @"!"]] forSection:1];
[self.tableViewDataSource setDataSource:[[SingleSelectionSingleSectionDataSource alloc] initWithArray:@[@"Hola", @"Mundo", @"!", @"¿Que tal?"]] forSection:2];
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self.tableViewDataSource selectedCellAtIndexPath:indexPath];
}
@end
您需要向数据源添加方法以获取选定的行。
获取示例:https://github.com/vikingosegundo/CompoundDatasourceExample
注意此代码存在单元重用问题。它已在 GitHub 上修复。