https://github.com/melvin7/MYTableViewManager
https://github.com/TimeFaceCoder/TFTableViewDataSource
TFTableViewDataSource 包含以下几个基本类
- TFTableViewDataSourceConfig : 用于配置列表数据获取接口,处理函数,分页记录数等
- TFTableViewDataSource : TableView数据源处理类,通过继承TFTableViewDataSource 可以重载下拉刷新,列表展示等方法来实现自定义
- TFTableViewDataManager 列表数据处理工具,所有的列表数据处理都需要继承TFTableViewDataManager来处理
- TFTableViewItem 单行列表数据源与事件处理类,所有的列表数据源都需要继承TFTableViewItem来处理
- TFTableViewItemCell 单行列表UI,所有的列表UI都需要继承TFTableViewItemCell来处理
1、回头看看,这框架还是很模糊啊;
DCSwitchTableViewItem
处理item点击事件有,onViewClickHandler,selectionHandler等;
2、DCManegerDataManeger,
TFTableViewDataManager初始化时initWithDataSource,会设置下_cellViewClickHandler;会先处理代理VC的事件
if ([strongSelf.tableViewDataSource.delegate respondsToSelector:@selector(actionOnView:actionType:)])
3、tableView Cell 响应事件;
DCManagerTableViewItem setSelectionHandler:)
tableView:didSelectRowAtIndexPath:
调用 MYTableViewItem 的 selectionHandler
TFTableViewItem : MYTableViewItem
单行列表数据源和事件处理类; 所有的列表数据源都要继承TFTableViewItem
来处理;
- (instancetype)init {
self = [super init];
if (!self) {
return nil;
}
__weak typeof(self) weakself = self;
self.selectionHandler = ^(id item){
if (weakself.onViewClickHandler) {
weakself.onViewClickHandler(item, -1);
}
};
return self;
}
在TFTableViewItem的init
方法中初始化了父类MYTableViewItem的selectionHandler;
里面调用自己的属性onViewClickHandler;而其初始化在temWithModel:clickHandler:中;
@property (nonatomic ,copy) void (^onViewClickHandler)(TFTableViewItem *item,NSInteger actionType);
???selectionHandler、onViewClickHandler在哪里调用的;
TFTableViewItemCell : MYTableViewCell
单行列表UI,所有的列表UI都继承自TFTableViewItemCell
来处理;
没有code, 主要看其父类MYTableViewCell : ASCellNode
- (instancetype)initWithTableViewItem:(MYTableViewItem *)tableViewItem {
self = [super init];
if(self) {
self.tableViewItem = tableViewItem;
// hairline cell separator
if (self.tableViewItem.separatorStyle != UITableViewCellSeparatorStyleNone) {
_dividerNode = [[ASDisplayNode alloc] init];
_dividerNode.backgroundColor = self.tableViewItem.dividerColor;
[self addSubnode:_dividerNode];
}
[self initCell];
}
return self;
}
MYTableViewCell继承自ASCellNode;整体基于ASTableView实现;
在initWithTableViewItem方法中设置列表数据源self.tableViewItem;调用initCell方法;
所以在我们自定义的cell中,在initCell中初始化UI;
ASDisplayKit中layout相当于layoutSubviews;重新布局;分为自动布局、手动布局;
TFTableViewDataManager : NSObject<TFTableViewDataManagerProtocol>
列表数据处理工具,所有的列表数据处理都需要继承TFTableViewDataManager
来处理;
管理类,管理cell数据源item,cell的UI-cell;
@interface TFTableViewDataManager : NSObject<TFTableViewDataManagerProtocol>
@property (nonatomic ,weak) TFTableViewDataSource *tableViewDataSource;
/**
* 列表内点击事件 block
*/
@property (nonatomic ,copy) CellViewClickHandler cellViewClickHandler;
/**
* 列表删除事件 block
*/
@property (nonatomic ,copy) DeletionHandlerWithCompletion deleteHanlder;
/**
* 当前cell的索引indexPath
*/
@property (nonatomic ,strong) NSIndexPath *currentIndexPath;
/**
* 对应的listType,绑定url
*/
@property (nonatomic ,assign) NSInteger listType;
/**
* 清除上面的block
*/
- (void)clearCompletionBlock;
@end
查看TFTableViewDataManager的实现;发现其initWithDataSource在dataSource中调用;
manager对dataSource弱引用;dataSource中对manager强引用;避免循环引用;
@implementation TFTableViewDataManager
- (instancetype)initWithDataSource:(TFTableViewDataSource *)tableViewDataSource
listType:(NSInteger)listType {
self = [super init];
if (!self) {
return nil;
}
_tableViewDataSource = tableViewDataSource;
_listType = listType;
__weak __typeof(self)weakSelf = self;
_cellViewClickHandler = ^ (TFTableViewItem *item ,NSInteger actionType) {
__typeof(&*weakSelf) strongSelf = weakSelf;
strongSelf.currentIndexPath = item.indexPath;
[item deselectRowAnimated:YES];
if ([strongSelf.tableViewDataSource.delegate respondsToSelector:@selector(actionOnView:actionType:)]) {
[strongSelf.tableViewDataSource.delegate actionOnView:item actionType:actionType];
}
[strongSelf cellViewClickHandler:item actionType:actionType];
};
_deleteHanlder = ^(TFTableViewItem *item ,Completion completion) {
__typeof(&*weakSelf) strongSelf = weakSelf;
[strongSelf deleteHanlder:item completion:completion];
};
return self;
}
/**
* 显示列表数据
*
* @param result 数据字典
* @param completionBlock 回调block
*/
- (void)reloadView:(NSDictionary *)result block:(TableViewReloadCompletionBlock)completionBlock {
}
/**
* 列表内View事件处理
*
* @param item
* @param actionType
*/
- (void)cellViewClickHandler:(TFTableViewItem *)item actionType:(NSInteger)actionType {
self.currentIndexPath = item.indexPath;
}
/**
* 列表删除事件处理
*
* @param item
*/
- (void)deleteHanlder:(TFTableViewItem *)item completion:(void (^)(void))completion {
self.currentIndexPath = item.indexPath;
}
/**
* 刷新指定Cell
*
* @param actionType
* @param dataId
*/
- (void)refreshCell:(NSInteger)actionType identifier:(NSString *)identifier {
}
- (void)clearCompletionBlock {
self.cellViewClickHandler = nil;
self.deleteHanlder = nil;
}
@end
在)initWithDataSource:listType:中初始化了cellViewClickHandler、deleteHanlder;
其中cellViewClickHandler中会回调datasource的代理类(通常为TFTableViewController的子类);这样就将cell的事件回传到ViewController了;
_cellViewClickHandler = ^ (TFTableViewItem *item ,NSInteger actionType) {
__typeof(&*weakSelf) strongSelf = weakSelf;
strongSelf.currentIndexPath = item.indexPath;
[item deselectRowAnimated:YES];
if ([strongSelf.tableViewDataSource.delegate respondsToSelector:@selector(actionOnView:actionType:)]) {
[strongSelf.tableViewDataSource.delegate actionOnView:item actionType:actionType];
}
[strongSelf cellViewClickHandler:item actionType:actionType];
};
看看协议接口TFTableViewDataManagerProtocol
有哪些东西;
ifndef TFTableViewDataManagerProtocol_h
#define TFTableViewDataManagerProtocol_h
#import "TFTableViewDataSource.h"
#import <TFNetwork/TFNetwork.h>
@class TFTableViewItem;
@class MYTableViewSection;
typedef void (^Completion)(void);
typedef void (^CellViewClickHandler)(__kindof TFTableViewItem *item ,NSInteger actionType);
typedef void (^DeletionHandlerWithCompletion)(__kindof TFTableViewItem *item, void (^)(void));
typedef void (^TableViewReloadCompletionBlock)(BOOL finished,id object,NSError *error, NSArray <MYTableViewSection *> *sections);
@protocol TFTableViewDataManagerProtocol <NSObject>
@required
/**
* 列表业务类初始化
*
* @param tableViewDataSource 列表数据源
* @param listType 列表类型
*
* @return TFTableDataSourceManager
*/
- (instancetype)initWithDataSource:(TFTableViewDataSource *)tableViewDataSource
listType:(NSInteger)listType;
/**
* 显示列表数据
*
* @param result 数据字典
* @param completionBlock 回调block
*/
- (void)reloadView:(NSDictionary *)result block:(TableViewReloadCompletionBlock)completionBlock;
/**
* 列表内View事件处理
*
* @param item
* @param actionType
*/
- (void)cellViewClickHandler:(TFTableViewItem *)item actionType:(NSInteger)actionType;
/**
* 列表删除事件处理
*
* @param item
*/
- (void)deleteHanlder:(TFTableViewItem *)item completion:(void (^)(void))completion;
/**
* 刷新指定Cell
*
* @param actionType
* @param dataId
*/
- (void)refreshCell:(NSInteger)actionType identifier:(NSString *)identifier;
@end
#endif
TFTableViewDataSource : NSObject
TabelView数据源处理类,通过继承TFTableViewDataSource
可以重载下拉刷新、列表展示等方法来实现自定义;
具体使用可以查看TFTableViewController;总体的逻辑参考RETableViewManager;两步:
- 绑定tableView到MYTableViewManager;
- 给tableViewManager手动设置item和itemCell;
_tableViewManager = [[MYTableViewManager alloc] initWithTableView:self.tableView delegate:nil];
_tableViewManager[@"TFTableviewDefaultItem"] = @"TFTableviewDefaultItemCell";
查看头文件
@protocol TFTableViewDataSourceDelegate <NSObject>
@required
/**
* 列表及其控件点击事件回调
*
* @param item
* @param actionType 事件类型
*/
- (void)actionOnView:(TFTableViewItem *)item actionType:(NSInteger)actionType;
/**
* 开始加载
*/
- (void)didStartLoad;
/**
* 加载完成
*
* @param loadPolicy 加载类型
* @param object 返回数据
* @param error 错误
*/
- (void)didFinishLoad:(TFDataLoadPolicy)loadPolicy object:(id)object error:(NSError *)error;
@optional
- (BOOL)showPullRefresh;
- (void)scrollViewDidScroll:(UIScrollView *)scrollView;
- (void)scrollViewDidScrollUp:(CGFloat)deltaY;
- (void)scrollViewDidScrollDown:(CGFloat)deltaY;
- (void)scrollFullScreenScrollViewDidEndDraggingScrollUp;
- (void)scrollFullScreenScrollViewDidEndDraggingScrollDown;
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate;
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath;
- (void)tableView:(ASTableView *)tableView willDisplayNodeForRowAtIndexPath:(NSIndexPath *)indexPath;
- (void)tableView:(ASTableView *)tableView didEndDisplayingNode:(ASCellNode *)node forRowAtIndexPath:(NSIndexPath *)indexPath;
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle
forRowAtIndexPath:(NSIndexPath *)indexPath;
@end
@interface TFTableViewDataSource : NSObject
@property (nonatomic ,weak) id<TFTableViewDataSourceDelegate> delegate;
@property (nonatomic ,strong ,readonly ,getter = manager) MYTableViewManager *manager;
@property (nonatomic ,weak) ASTableView *tableView;
@property (nonatomic ,assign) TFDataSourceState dataSourceState;
/**
* 总页数
*/
@property (nonatomic ,assign) NSInteger totalPage;
/**
* 当前页码
*/
@property (nonatomic ,assign) NSInteger currentPage;
/**
* 对应的listType,绑定url
*/
@property (nonatomic ,assign) NSInteger listType;
/**
* 列表数据缓存时间
*/
@property (nonatomic ,assign) NSInteger cacheTimeInSeconds;
/**
* 初始化化方法,用于绑定manager和tableview;item和itemCell;
*
*/
- (instancetype)initWithTableView:(ASTableView *)tableView
listType:(NSInteger)listType
params:(NSDictionary *)params
delegate:(id /*<TFTableViewDataSourceDelegate>*/)delegate;
/**
* 开始加载,没有url参数
*/
- (void)startLoading;
/**
* 开始加载列表数据,带url参数
*
* @param params GET 请求参数
*/
- (void)startLoadingWithParams:(NSDictionary *)params;
/**
* 停止加载
*/
- (void)stopLoading;
/**
* 刷新指定Cell
*
* @param actionType 刷新动作
* @param identifier Cell唯一标示
*/
- (void)refreshCell:(NSInteger)actionType identifier:(NSString *)identifier;
/**
* 下拉刷新相关
*/
- (void)initTableViewPullRefresh;
- (void)startTableViewPullRefresh;
- (void)stopTableViewPullRefresh;
@end
查看实现方法:
一. 初始化init开始;
- (instancetype)initWithTableView:(ASTableView *)tableView
listType:(NSInteger)listType
params:(NSDictionary *)params
delegate:(id /*<TFTableViewDataSourceDelegate>*/)delegate {
self = [super init];
if (!self) {
return nil;
}
_delegate = delegate;
_tableView = tableView;
_listType = listType;
_requestArgument = [NSMutableDictionary dictionaryWithDictionary:params];
_manager = [[MYTableViewManager alloc] initWithTableView:tableView delegate:self];
[self initTableViewPullRefresh];
[self setupDataSource];
return self;
}
初始化请求参数requestArgument,MYTableViewManager;调用initTableViewPullRefresh初始化下拉刷新;调用setupDataSource方法,进行一些初始化配置,根据listType获取对应的url和dataManager;
#pragma mark - 初始化数据加载方法
- (void)setupDataSource {
_downThresholdY = 200.0;
_upThresholdY = 25.0;
NSString *requestURL = [[TFTableViewDataSourceConfig sharedInstance] requestURLByListType:_listType];
NSString *className = [[TFTableViewDataSourceConfig sharedInstance] classNameByListType:_listType];
_dataRequest = [[TFTableViewDataRequest alloc] initWithRequestURL:requestURL params:_requestArgument];
if (className) {
Class class = NSClassFromString(className);
_tableViewDataManager = [[class alloc] initWithDataSource:self listType:_listType];
}
//registerClass
NSArray *itemClassList = [TFTableViewClassList subclassesOfClass:[MYTableViewItem class]];
for (Class itemClass in itemClassList) {
NSString *itemName = NSStringFromClass(itemClass);
self.manager[itemName] = [itemName stringByAppendingString:@"Cell"];
}
}
在RouteManager中setupMap配置信息如下;
[self mapWithListType:ListTypeManagerCreateList
dataManagerClass:@"DCManegerDataManeger"
url:kDCInterfaceManagerRoot];
看看mapWithListType怎么实现的;最后调用TFTableViewDataSourceConfig方法;
+ (void)mapWithListType:(ListType)listType dataManagerClass:(NSString *)className url:(NSString *)url {
[[TFTableViewDataSourceConfig sharedInstance]
mapWithListType:listType
mappingInfo:@{ kTFTableViewDataManagerClassKey : className,
kTFTableViewDataRequestURLKey : url }];
}
返回查看setupDataSource方法;就获取到相应的requestURL和ViewDataManager类名;
对DataManager进行实例化;通过TFTableViewClassList获取所有MYTableViewItem的子类,这是通过runtime实现的,之后给manger配置item和itemCell,像下面这样;
_tableViewManager = [[MYTableViewManager alloc] initWithTableView:self.tableView delegate:nil];
_tableViewManager[@"TFTableviewDefaultItem"] = @"TFTableviewDefaultItemCell";
二. 数据加载loading;
// 开始加载,
- (void)startLoading {
[self startLoadingWithParams:_requestArgument];
}
// 带参数 加载;
- (void)startLoadingWithParams:(NSDictionary *)params {
if (_requestArgument) {
[_requestArgument addEntriesFromDictionary:params];
}
else {
_requestArgument = [NSMutableDictionary dictionaryWithDictionary:params];
}
[self load:TFDataLoadPolicyNone context:nil];
}
???疑问,这样调用,参数会重复吗;
[self.requestParams setObject:@(model.id) forKey:@"city"];
[self.dataSource startLoadingWithParams:self.requestParams];
数据加载核心方法
// 数据加载
- (void)load:(TFDataLoadPolicy)loadPolicy context:(ASBatchContext *)context {
//当前正在加载数据
if (_dataSourceState == TFDataSourceStateLoading) {
return;
}
if (loadPolicy == TFDataLoadPolicyMore) {
//加载下一页数据
if (_currentPage == _totalPage) {
//加载完所有页码
_dataSourceState = TFDataSourceStateFinished;
return;
}
_currentPage++;
} else {
_currentPage = 1;
_totalPage = 1;
}
[_requestArgument setObject:[NSNumber numberWithInteger:[TFTableViewDataSourceConfig pageSize]]
forKey:@"pageSize"];
[_requestArgument setObject:[NSNumber numberWithInteger:_currentPage] forKey:@"currentPage"];
_dataRequest.requestArgument = _requestArgument;
// 设置缓存时间
_dataRequest.cacheTimeInSeconds = _cacheTimeInSeconds;
// 设置操作标示
_dataSourceState = TFDataSourceStateLoading;
// 加载第一页时候使用缓存数据
if ([_dataRequest cacheResponseObject] && !_firstLoadOver) {
// 使用缓存数据绘制UI
TFTableViewLogDebug(@"use cache data for %@",_dataRequest.requestURL);
[self handleResultData:[_dataRequest cacheResponseObject]
dataLoadPolicy:TFDataLoadPolicyCache
context:context
error:nil];
}
else {
// 请求网络数据
[_dataRequest startWithCompletionBlockWithSuccess:^(__kindof TFBaseRequest *request) {
TFTableViewLogDebug(@"get data from server %@ page:%@",request.requestUrl,@(_currentPage));
[self handleResultData:request.responseObject dataLoadPolicy:loadPolicy context:context error:nil];
} failure:^(__kindof TFBaseRequest *request) {
TFTableViewLogDebug(@"get data from %@ error :%@ userinfo:%@",request.requestUrl,request.error,request.userInfo);
// 网络请求出错,存在缓存,先获取缓存
if ([request cacheResponseObject]) {
[self handleResultData:[request cacheResponseObject]
dataLoadPolicy:loadPolicy
context:context
error:nil];
}
else {
[self handleResultData:nil
dataLoadPolicy:loadPolicy
context:context
error:request.error];
}
}];
}
}
设置请求参数、请求缓存时间;有缓存先用缓存绘制UI,不然网络请求数据;网络请求出现错误的时候,也会先使用缓存;
// 处理返回数据并绘制UI
- (void)handleResultData:(NSDictionary *)result
dataLoadPolicy:(TFDataLoadPolicy)dataLoadPolicy
context:(ASBatchContext *)context
error:(NSError *)error {
TFTableViewLogDebug(@"%s",__func__);
NSError *hanldeError = nil;
NSInteger lastSectionIndex = [[self.manager sections] count] - 1;
if (!result || [[result objectForKey:@"dataList"] count] <= 0) {
//数据为空
hanldeError = [NSError errorWithDomain:@"" code:1 userInfo:@{}];
}
if (dataLoadPolicy == TFDataLoadPolicyMore) {
//加载下一页,移除loading item
[self.manager removeLastSection];
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView deleteSections:[NSIndexSet indexSetWithIndex:lastSectionIndex]
withRowAnimation:UITableViewRowAnimationFade];
});
}
[self setTotalPage:[[result objectForKey:@"totalPage"] integerValue]];
if (_totalPage == 0) {
//数据边界检查
_totalPage = 1;
_currentPage = 1;
}
// 调用tableViewManager 的 reloadView:block方法 显示列表数据;
// 在这里将数据传给DataManager的子类;调用block
__weak __typeof(self)weakSelf = self;
[self.tableViewDataManager reloadView:result
block:^(BOOL finished, id object, NSError *error, NSArray <MYTableViewSection *> *sections)
{
typeof(self) strongSelf = weakSelf;
if (finished) {
if (dataLoadPolicy == TFDataLoadPolicyReload || dataLoadPolicy == TFDataLoadPolicyNone) {
// 重新加载列表数据
[strongSelf.manager removeAllSections];
}
NSInteger rangelocation = [strongSelf.manager.sections count];
[strongSelf.manager addSectionsFromArray:sections];
NSInteger rangelength = 1;
// 需要在主线程执行
if (_currentPage < _totalPage) {
// 存在下一页数据,在列表尾部追加loading item
MYTableViewSection *section = [MYTableViewSection section];
// loading item
[section addItem:[MYTableViewLoadingItem itemWithTitle:NSLocalizedString(@"正在加载...", nil)]];
[strongSelf.manager addSection:section];
rangelength += sections.count;
}
dispatch_async(dispatch_get_main_queue(), ^{
if (dataLoadPolicy == TFDataLoadPolicyMore) {
[strongSelf.tableView insertSections:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(rangelocation, rangelength)]
withRowAnimation:UITableViewRowAnimationFade];
if (context) {
[context completeBatchFetching:YES];
}
}
else {
[strongSelf reloadTableView];
strongSelf.firstLoadOver = YES;
if (dataLoadPolicy == TFDataLoadPolicyReload) {
[strongSelf stopTableViewPullRefresh];
}
if (dataLoadPolicy == TFDataLoadPolicyCache) {
//第一次从缓存加载数据后延迟触发下拉刷新重新加载
[strongSelf performSelector:@selector(startTableViewPullRefresh)
withObject:nil
afterDelay:0.75];
}
}
// 数据加载完成
if (strongSelf.delegate && [strongSelf.delegate respondsToSelector:@selector(didFinishLoad:object:error:)]) {
[strongSelf.delegate didFinishLoad:dataLoadPolicy object:object error:error?error:hanldeError];
}
});
strongSelf.dataSourceState = TFDataSourceStateFinished;
}
}];
}
调用tableViewManager 的 reloadView:block方法 显示列表数据;在这里将数据传给DataManager的子类;调用block;
// 重新加载列表数据;remove所有section了;
[strongSelf.manager removeAllSections];
最后数据加载完成,回调dataSource的代理(通常为TFTableView的子类);
didFinishLoad:object:error:
通过源码看到,reloadView中将数据通过block传过去,在VC中didFinishLoad才能进行判断;
DataManager 给 ViewController 传数据;
??? 那反过来呢;
typedef void (^TableViewReloadCompletionBlock)(BOOL finished,id object,NSError *error, NSArray <MYTableViewSection *> *sections);
- (void)reloadView:(NSDictionary *)result block:(TableViewReloadCompletionBlock)completionBlock
completionBlock(YES, list, nil, @[section]);
- (void)didFinishLoad:(TFDataLoadPolicy)loadPolicy object:(id)object error:(NSError *)error
{
[super didFinishLoad:loadPolicy object:object error:error];
if (!object)
{
[self showStateView:kTFViewStateNoData];
}
}
MYTableViewManager
最终tableView的cell绘制都在这个MYTableViewManager中;
MYTableViewManager的整体逻辑可以参考RETableViewManager;只是将RE里的UITableView
换成ASTableView;
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
// 返回对应的cell;ASTableView中称为node;
- (ASCellNode *)tableView:(ASTableView *)tableView nodeForRowAtIndexPath:(NSIndexPath *)indexPath
// tableView的侧边IndexTitles
- (NSArray *)sectionIndexTitlesForTableView:(ASTableView *)tableView
// tableView尾视图Header 的 title
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
// tableView尾视图Footer 的 title
- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section
// tableView移动move
// 可以看到moveHandler、moveCompletionHandler功能;怎么用的
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
// 看到给item添加editingStyle,就能实现左划删除等;
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
- (void)tableView:(ASTableView *)tableView willDisplayNodeForRowAtIndexPath:(NSIndexPath *)indexPath
- (void)tableView:(ASTableView *)tableView didEndDisplayingNode:(ASCellNode *)node forRowAtIndexPath:(NSIndexPath *)indexPath
tableView如何实现删除,
// tableView如何实现删除; section删掉,tableView删掉,还要修改后面
[section removeItemAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
for (NSInteger i = indexPath.row; i < section.items.count; i++) {
MYTableViewItem *afterItem = [[section items] objectAtIndex:i];
MYTableViewCell *cell = (MYTableViewCell *)[(ASTableView *)tableView nodeForRowAtIndexPath:afterItem.indexPath];
cell.rowIndex--;
}
Tableview delegate
// Header、Footer
- (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section
- (void)tableView:(UITableView *)tableView willDisplayFooterView:(UIView *)view forSection:(NSInteger)section
- (void)tableView:(UITableView *)tableView didEndDisplayingHeaderView:(UIView *)view forSection:(NSInteger)section
- (void)tableView:(UITableView *)tableView didEndDisplayingFooterView:(UIView *)view forSection:(NSInteger)section
// header、Footer的高度
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)sectionIndex
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)sectionIndex
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)sectionIndex
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)sectionIndex
// Accessories (disclosures).
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath
// Selection
- (BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath
- (void)tableView:(UITableView *)tableView didHighlightRowAtIndexPath:(NSIndexPath *)indexPath
- (void)tableView:(UITableView *)tableView didUnhighlightRowAtIndexPath:(NSIndexPath *)indexPath
tableView 事件处理
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
- (NSIndexPath *)tableView:(UITableView *)tableView willDeselectRowAtIndexPath:(NSIndexPath *)indexPath
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
// Editing
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
// 左滑删除、标题;
- (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath
- (BOOL)tableView:(UITableView *)tableView shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath
- (void)tableView:(UITableView*)tableView willBeginEditingRowAtIndexPath:(NSIndexPath *)indexPath
- (void)tableView:(UITableView*)tableView didEndEditingRowAtIndexPath:(NSIndexPath *)indexPath
// Moving/reordering
- (NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath
// Indentation
- (NSInteger)tableView:(UITableView *)tableView indentationLevelForRowAtIndexPath:(NSIndexPath *)indexPath
// Copy/Paste. All three methods must be implemented by the delegate.
// 复制/粘贴;
- (BOOL)tableView:(UITableView *)tableView shouldShowMenuForRowAtIndexPath:(NSIndexPath *)indexPath
- (BOOL)tableView:(UITableView *)tableView canPerformAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender
其他的代理不看了;分析下tableView的事件处理;
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[_tableView deselectRowAtIndexPath:indexPath animated:YES];
[_tableView beginUpdates];
MYTableViewSection *section = [self.mutableSections objectAtIndex:indexPath.section];
id item = [section.items objectAtIndex:indexPath.row];
if ([item respondsToSelector:@selector(setSelectionHandler:)]) {
MYTableViewItem *actionItem = (MYTableViewItem *)item;
if (actionItem.selectionHandler)
actionItem.selectionHandler(item);
}
// Forward to UITableView delegate
//
if ([self.delegate conformsToProtocol:@protocol(UITableViewDelegate)] && [self.delegate respondsToSelector:@selector(tableView:didSelectRowAtIndexPath:)])
[self.delegate tableView:tableView didSelectRowAtIndexPath:indexPath];
[_tableView endUpdates];
}
获取相应的section,获取item;调用item的selectionHandler,并将item作为block参数回传过去;
TFTableViewItem 在初始化会设置selectionHandler
- (instancetype)init {
self = [super init];
if (!self) {
return nil;
}
__weak typeof(self) weakself = self;
self.selectionHandler = ^(id item){
if (weakself.onViewClickHandler) {
weakself.onViewClickHandler(item, -1);
}
};
return self;
}
+ (instancetype)itemWithModel:(NSObject *)model
clickHandler:(void(^)(TFTableViewItem *item,NSInteger actionType))clickHandler {
TFTableViewItem *item = [[[self class] alloc] init];
item.model = model;
item.onViewClickHandler = clickHandler;
return item;
}
在init中将actionType设为-1;作为整个cell的点击;其他非零值可以为cell上的按钮;并且将item值回传给onViewClickHandler;
TFTableViewDataManager中会初始化cellViewClickHandler;其中的item是TFTableViewItem传过来的;
- (instancetype)initWithDataSource:(TFTableViewDataSource *)tableViewDataSource
listType:(NSInteger)listType {
self = [super init];
if (!self) {
return nil;
}
_tableViewDataSource = tableViewDataSource;
_listType = listType;
__weak __typeof(self)weakSelf = self;
_cellViewClickHandler = ^ (TFTableViewItem *item ,NSInteger actionType) {
__typeof(&*weakSelf) strongSelf = weakSelf;
strongSelf.currentIndexPath = item.indexPath;
[item deselectRowAnimated:YES];
if ([strongSelf.tableViewDataSource.delegate respondsToSelector:@selector(actionOnView:actionType:)]) {
[strongSelf.tableViewDataSource.delegate actionOnView:item actionType:actionType];
}
[strongSelf cellViewClickHandler:item actionType:actionType];
};
_deleteHanlder = ^(TFTableViewItem *item ,Completion completion) {
__typeof(&*weakSelf) strongSelf = weakSelf;
[strongSelf deleteHanlder:item completion:completion];
};
return self;
}
cellViewClickHandler中,
首先会调用tableViewDataSource.delegate
的方法actionOnView:actionType:
; 一般为TFTableViewController
的子类;
然后再调用对应TFTableViewDataManager
子类的cellViewClickHandler:actionType: