https://github.com/melvin7/MYTableViewManager
https://github.com/TimeFaceCoder/TFTableViewDataSource
TFTableViewDataSource 包含以下幾個(gè)基本類
- TFTableViewDataSourceConfig : 用于配置列表數(shù)據(jù)獲取接口错沽,處理函數(shù),分頁(yè)記錄數(shù)等
- TFTableViewDataSource : TableView數(shù)據(jù)源處理類例隆,通過(guò)繼承TFTableViewDataSource 可以重載下拉刷新甥捺,列表展示等方法來(lái)實(shí)現(xiàn)自定義
- TFTableViewDataManager 列表數(shù)據(jù)處理工具,所有的列表數(shù)據(jù)處理都需要繼承TFTableViewDataManager來(lái)處理
- TFTableViewItem 單行列表數(shù)據(jù)源與事件處理類镀层,所有的列表數(shù)據(jù)源都需要繼承TFTableViewItem來(lái)處理
- TFTableViewItemCell 單行列表UI镰禾,所有的列表UI都需要繼承TFTableViewItemCell來(lái)處理
1皿曲、回頭看看,這框架還是很模糊拔庹臁屋休;
DCSwitchTableViewItem
處理item點(diǎn)擊事件有,onViewClickHandler备韧,selectionHandler等劫樟;
2、DCManegerDataManeger织堂,
TFTableViewDataManager初始化時(shí)initWithDataSource叠艳,會(huì)設(shè)置下_cellViewClickHandler;會(huì)先處理代理VC的事件
if ([strongSelf.tableViewDataSource.delegate respondsToSelector:@selector(actionOnView:actionType:)])
3易阳、tableView Cell 響應(yīng)事件附较;
DCManagerTableViewItem setSelectionHandler:)
tableView:didSelectRowAtIndexPath:
調(diào)用 MYTableViewItem 的 selectionHandler
TFTableViewItem : MYTableViewItem
單行列表數(shù)據(jù)源和事件處理類; 所有的列表數(shù)據(jù)源都要繼承TFTableViewItem
來(lái)處理;
- (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潦俺;
里面調(diào)用自己的屬性onViewClickHandler拒课;而其初始化在temWithModel:clickHandler:中;
@property (nonatomic ,copy) void (^onViewClickHandler)(TFTableViewItem *item,NSInteger actionType);
事示?早像??selectionHandler肖爵、onViewClickHandler在哪里調(diào)用的卢鹦;
TFTableViewItemCell : MYTableViewCell
單行列表UI,所有的列表UI都繼承自TFTableViewItemCell
來(lái)處理遏匆;
沒有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實(shí)現(xiàn)幅聘;
在initWithTableViewItem方法中設(shè)置列表數(shù)據(jù)源self.tableViewItem;調(diào)用initCell方法窃植;
所以在我們自定義的cell中帝蒿,在initCell中初始化UI;
ASDisplayKit中l(wèi)ayout相當(dāng)于layoutSubviews巷怜;重新布局葛超;分為自動(dòng)布局、手動(dòng)布局延塑;
TFTableViewDataManager : NSObject<TFTableViewDataManagerProtocol>
列表數(shù)據(jù)處理工具绣张,所有的列表數(shù)據(jù)處理都需要繼承TFTableViewDataManager
來(lái)處理;
管理類关带,管理cell數(shù)據(jù)源item侥涵,cell的UI-cell;
@interface TFTableViewDataManager : NSObject<TFTableViewDataManagerProtocol>
@property (nonatomic ,weak) TFTableViewDataSource *tableViewDataSource;
/**
* 列表內(nèi)點(diǎn)擊事件 block
*/
@property (nonatomic ,copy) CellViewClickHandler cellViewClickHandler;
/**
* 列表刪除事件 block
*/
@property (nonatomic ,copy) DeletionHandlerWithCompletion deleteHanlder;
/**
* 當(dāng)前cell的索引indexPath
*/
@property (nonatomic ,strong) NSIndexPath *currentIndexPath;
/**
* 對(duì)應(yīng)的listType,綁定url
*/
@property (nonatomic ,assign) NSInteger listType;
/**
* 清除上面的block
*/
- (void)clearCompletionBlock;
@end
查看TFTableViewDataManager的實(shí)現(xiàn)芜飘;發(fā)現(xiàn)其initWithDataSource在dataSource中調(diào)用务豺;
manager對(duì)dataSource弱引用;dataSource中對(duì)manager強(qiáng)引用嗦明;避免循環(huán)引用笼沥;
@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;
}
/**
* 顯示列表數(shù)據(jù)
*
* @param result 數(shù)據(jù)字典
* @param completionBlock 回調(diào)block
*/
- (void)reloadView:(NSDictionary *)result block:(TableViewReloadCompletionBlock)completionBlock {
}
/**
* 列表內(nèi)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中會(huì)回調(diào)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];
};
看看協(xié)議接口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
/**
* 列表業(yè)務(wù)類初始化
*
* @param tableViewDataSource 列表數(shù)據(jù)源
* @param listType 列表類型
*
* @return TFTableDataSourceManager
*/
- (instancetype)initWithDataSource:(TFTableViewDataSource *)tableViewDataSource
listType:(NSInteger)listType;
/**
* 顯示列表數(shù)據(jù)
*
* @param result 數(shù)據(jù)字典
* @param completionBlock 回調(diào)block
*/
- (void)reloadView:(NSDictionary *)result block:(TableViewReloadCompletionBlock)completionBlock;
/**
* 列表內(nèi)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數(shù)據(jù)源處理類乘凸,通過(guò)繼承TFTableViewDataSource
可以重載下拉刷新、列表展示等方法來(lái)實(shí)現(xiàn)自定義累榜;
具體使用可以查看TFTableViewController营勤;總體的邏輯參考RETableViewManager;兩步:
- 綁定tableView到MYTableViewManager;
- 給tableViewManager手動(dòng)設(shè)置item和itemCell壹罚;
_tableViewManager = [[MYTableViewManager alloc] initWithTableView:self.tableView delegate:nil];
_tableViewManager[@"TFTableviewDefaultItem"] = @"TFTableviewDefaultItemCell";
查看頭文件
@protocol TFTableViewDataSourceDelegate <NSObject>
@required
/**
* 列表及其控件點(diǎn)擊事件回調(diào)
*
* @param item
* @param actionType 事件類型
*/
- (void)actionOnView:(TFTableViewItem *)item actionType:(NSInteger)actionType;
/**
* 開始加載
*/
- (void)didStartLoad;
/**
* 加載完成
*
* @param loadPolicy 加載類型
* @param object 返回?cái)?shù)據(jù)
* @param error 錯(cuò)誤
*/
- (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;
/**
* 總頁(yè)數(shù)
*/
@property (nonatomic ,assign) NSInteger totalPage;
/**
* 當(dāng)前頁(yè)碼
*/
@property (nonatomic ,assign) NSInteger currentPage;
/**
* 對(duì)應(yīng)的listType葛作,綁定url
*/
@property (nonatomic ,assign) NSInteger listType;
/**
* 列表數(shù)據(jù)緩存時(shí)間
*/
@property (nonatomic ,assign) NSInteger cacheTimeInSeconds;
/**
* 初始化化方法,用于綁定manager和tableview猖凛;item和itemCell赂蠢;
*
*/
- (instancetype)initWithTableView:(ASTableView *)tableView
listType:(NSInteger)listType
params:(NSDictionary *)params
delegate:(id /*<TFTableViewDataSourceDelegate>*/)delegate;
/**
* 開始加載,沒有url參數(shù)
*/
- (void)startLoading;
/**
* 開始加載列表數(shù)據(jù)辨泳,帶url參數(shù)
*
* @param params GET 請(qǐng)求參數(shù)
*/
- (void)startLoadingWithParams:(NSDictionary *)params;
/**
* 停止加載
*/
- (void)stopLoading;
/**
* 刷新指定Cell
*
* @param actionType 刷新動(dòng)作
* @param identifier Cell唯一標(biāo)示
*/
- (void)refreshCell:(NSInteger)actionType identifier:(NSString *)identifier;
/**
* 下拉刷新相關(guān)
*/
- (void)initTableViewPullRefresh;
- (void)startTableViewPullRefresh;
- (void)stopTableViewPullRefresh;
@end
查看實(shí)現(xiàn)方法:
一. 初始化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;
}
初始化請(qǐng)求參數(shù)requestArgument,MYTableViewManager菠红;調(diào)用initTableViewPullRefresh初始化下拉刷新第岖;調(diào)用setupDataSource方法,進(jìn)行一些初始化配置试溯,根據(jù)listType獲取對(duì)應(yīng)的url和dataManager蔑滓;
#pragma mark - 初始化數(shù)據(jù)加載方法
- (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怎么實(shí)現(xiàn)的遇绞;最后調(diào)用TFTableViewDataSourceConfig方法键袱;
+ (void)mapWithListType:(ListType)listType dataManagerClass:(NSString *)className url:(NSString *)url {
[[TFTableViewDataSourceConfig sharedInstance]
mapWithListType:listType
mappingInfo:@{ kTFTableViewDataManagerClassKey : className,
kTFTableViewDataRequestURLKey : url }];
}
返回查看setupDataSource方法;就獲取到相應(yīng)的requestURL和ViewDataManager類名摹闽;
對(duì)DataManager進(jìn)行實(shí)例化蹄咖;通過(guò)TFTableViewClassList獲取所有MYTableViewItem的子類,這是通過(guò)runtime實(shí)現(xiàn)的付鹿,之后給manger配置item和itemCell澜汤,像下面這樣铝量;
_tableViewManager = [[MYTableViewManager alloc] initWithTableView:self.tableView delegate:nil];
_tableViewManager[@"TFTableviewDefaultItem"] = @"TFTableviewDefaultItemCell";
二. 數(shù)據(jù)加載loading;
// 開始加載银亲,
- (void)startLoading {
[self startLoadingWithParams:_requestArgument];
}
// 帶參數(shù) 加載慢叨;
- (void)startLoadingWithParams:(NSDictionary *)params {
if (_requestArgument) {
[_requestArgument addEntriesFromDictionary:params];
}
else {
_requestArgument = [NSMutableDictionary dictionaryWithDictionary:params];
}
[self load:TFDataLoadPolicyNone context:nil];
}
?务蝠?拍谐?疑問(wèn),這樣調(diào)用馏段,參數(shù)會(huì)重復(fù)嗎轩拨;
[self.requestParams setObject:@(model.id) forKey:@"city"];
[self.dataSource startLoadingWithParams:self.requestParams];
數(shù)據(jù)加載核心方法
// 數(shù)據(jù)加載
- (void)load:(TFDataLoadPolicy)loadPolicy context:(ASBatchContext *)context {
//當(dāng)前正在加載數(shù)據(jù)
if (_dataSourceState == TFDataSourceStateLoading) {
return;
}
if (loadPolicy == TFDataLoadPolicyMore) {
//加載下一頁(yè)數(shù)據(jù)
if (_currentPage == _totalPage) {
//加載完所有頁(yè)碼
_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;
// 設(shè)置緩存時(shí)間
_dataRequest.cacheTimeInSeconds = _cacheTimeInSeconds;
// 設(shè)置操作標(biāo)示
_dataSourceState = TFDataSourceStateLoading;
// 加載第一頁(yè)時(shí)候使用緩存數(shù)據(jù)
if ([_dataRequest cacheResponseObject] && !_firstLoadOver) {
// 使用緩存數(shù)據(jù)繪制UI
TFTableViewLogDebug(@"use cache data for %@",_dataRequest.requestURL);
[self handleResultData:[_dataRequest cacheResponseObject]
dataLoadPolicy:TFDataLoadPolicyCache
context:context
error:nil];
}
else {
// 請(qǐng)求網(wǎng)絡(luò)數(shù)據(jù)
[_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);
// 網(wǎng)絡(luò)請(qǐng)求出錯(cuò),存在緩存院喜,先獲取緩存
if ([request cacheResponseObject]) {
[self handleResultData:[request cacheResponseObject]
dataLoadPolicy:loadPolicy
context:context
error:nil];
}
else {
[self handleResultData:nil
dataLoadPolicy:loadPolicy
context:context
error:request.error];
}
}];
}
}
設(shè)置請(qǐng)求參數(shù)亡蓉、請(qǐng)求緩存時(shí)間;有緩存先用緩存繪制UI喷舀,不然網(wǎng)絡(luò)請(qǐng)求數(shù)據(jù)砍濒;網(wǎng)絡(luò)請(qǐng)求出現(xiàn)錯(cuò)誤的時(shí)候,也會(huì)先使用緩存硫麻;
// 處理返回?cái)?shù)據(jù)并繪制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) {
//數(shù)據(jù)為空
hanldeError = [NSError errorWithDomain:@"" code:1 userInfo:@{}];
}
if (dataLoadPolicy == TFDataLoadPolicyMore) {
//加載下一頁(yè)爸邢,移除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) {
//數(shù)據(jù)邊界檢查
_totalPage = 1;
_currentPage = 1;
}
// 調(diào)用tableViewManager 的 reloadView:block方法 顯示列表數(shù)據(jù);
// 在這里將數(shù)據(jù)傳給DataManager的子類拿愧;調(diào)用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) {
// 重新加載列表數(shù)據(jù)
[strongSelf.manager removeAllSections];
}
NSInteger rangelocation = [strongSelf.manager.sections count];
[strongSelf.manager addSectionsFromArray:sections];
NSInteger rangelength = 1;
// 需要在主線程執(zhí)行
if (_currentPage < _totalPage) {
// 存在下一頁(yè)數(shù)據(jù)杠河,在列表尾部追加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) {
//第一次從緩存加載數(shù)據(jù)后延遲觸發(fā)下拉刷新重新加載
[strongSelf performSelector:@selector(startTableViewPullRefresh)
withObject:nil
afterDelay:0.75];
}
}
// 數(shù)據(jù)加載完成
if (strongSelf.delegate && [strongSelf.delegate respondsToSelector:@selector(didFinishLoad:object:error:)]) {
[strongSelf.delegate didFinishLoad:dataLoadPolicy object:object error:error?error:hanldeError];
}
});
strongSelf.dataSourceState = TFDataSourceStateFinished;
}
}];
}
調(diào)用tableViewManager 的 reloadView:block方法 顯示列表數(shù)據(jù);在這里將數(shù)據(jù)傳給DataManager的子類浇辜;調(diào)用block券敌;
// 重新加載列表數(shù)據(jù);remove所有section了柳洋;
[strongSelf.manager removeAllSections];
最后數(shù)據(jù)加載完成待诅,回調(diào)dataSource的代理(通常為TFTableView的子類);
didFinishLoad:object:error:
通過(guò)源碼看到膳灶,reloadView中將數(shù)據(jù)通過(guò)block傳過(guò)去咱士,在VC中didFinishLoad才能進(jìn)行判斷;
DataManager 給 ViewController 傳數(shù)據(jù)轧钓;
??? 那反過(guò)來(lái)呢;
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繪制都在這個(gè)MYTableViewManager中锐膜;
MYTableViewManager的整體邏輯可以參考RETableViewManager;只是將RE里的UITableView
換成ASTableView毕箍;
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
// 返回對(duì)應(yīng)的cell;ASTableView中稱為node道盏;
- (ASCellNode *)tableView:(ASTableView *)tableView nodeForRowAtIndexPath:(NSIndexPath *)indexPath
// tableView的側(cè)邊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移動(dòng)move
// 可以看到moveHandler而柑、moveCompletionHandler功能文捶;怎么用的
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
// 看到給item添加editingStyle,就能實(shí)現(xiàn)左劃刪除等媒咳;
- (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如何實(shí)現(xiàn)刪除粹排,
// tableView如何實(shí)現(xiàn)刪除; 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
// 左滑刪除妙同、標(biāo)題射富;
- (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.
// 復(fù)制/粘貼;
- (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];
}
獲取相應(yīng)的section,獲取item芒涡;調(diào)用item的selectionHandler柴灯,并將item作為block參數(shù)回傳過(guò)去;
TFTableViewItem 在初始化會(huì)設(shè)置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設(shè)為-1费尽;作為整個(gè)cell的點(diǎn)擊弛槐;其他非零值可以為cell上的按鈕;并且將item值回傳給onViewClickHandler依啰;
TFTableViewDataManager中會(huì)初始化cellViewClickHandler乎串;其中的item是TFTableViewItem傳過(guò)來(lái)的;
- (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中速警,
首先會(huì)調(diào)用tableViewDataSource.delegate
的方法actionOnView:actionType:
叹誉; 一般為TFTableViewController
的子類;
然后再調(diào)用對(duì)應(yīng)TFTableViewDataManager
子類的cellViewClickHandler:actionType:
Objective-C如何自己實(shí)現(xiàn)一個(gè)基于數(shù)組下標(biāo)的屬性訪問(wèn)模式