nimbuskit这个三方其实很大,东西非常多
比如支持超链接的label 、web view 组件 、标准化的程序通信 、强大的debug工具 等等。
因为项目需求,所以看了一遍它关于它模块化组装tableview的源码。。做个笔记记录
它的结构其实类似于早期我们cell部分cellModel的封装,进一步的封装了cell形成,只不过它做的封装更为完善一些,但是也有一些不足
源码部分分为了几大块,表格的代理 NITableViewActions,数据源 NITableViewModel
下面看看具体的核心类目,其余常规类目暂时不看
数据代理类目:
@interface NIObjectActions : NSObject
@property (nonatomic, copy) NIActionBlock tapAction;
@property (nonatomic, copy) NIActionBlock detailAction;
@property (nonatomic, copy) NIActionBlock navigateAction;
@property (nonatomic) SEL tapSelector;
@property (nonatomic) SEL detailSelector;
@property (nonatomic) SEL navigateSelector;
@end
NIActions : NSObject
@property (nonatomic, strong) NSMutableDictionary* objectToAction;<object.hash,NIObjectActions>
@property (nonatomic, strong) NSMutableDictionary* classToAction;<class,NIObjectActions>
@property (nonatomic, strong) NSMutableSet* objectSet; <NIObjectActions>
- (id)attachToObject:(id<NSObject>)object tapBlock:(NIActionBlock)action;
。。。 - (id)attachToObject:(id<NSObject>)object tapSelector:(SEL)selector;
。。。
pragma mark Mapping Classes
- (void)attachToClass:(Class)aClass tapBlock:(NIActionBlock)action;
。。。 - (void)attachToClass:(Class)aClass tapSelector:(SEL)selector;
。。。。
主代理类目期内实现了table的代理方法,通过NIActions定义了基本的行为方式监听
NITableViewActions : NIActions <UITableViewDelegate>
NSMutableSet* forwardDelegates;
数据源类目:
section独立单位
@interface NITableViewModelSection : NSObject
- (id)section;
@property (nonatomic, copy) NSString* headerTitle;
@property (nonatomic, copy) NSString* footerTitle;
@property (nonatomic, strong) NSArray* rows; —> string/NITableViewModelFooter/cusdefineObject
@end
主数据源类目
@interface NITableViewModel : NSObject <NIActionsDataSource, UITableViewDataSource>
( NIActionsDataSource :- (id)objectAtIndexPath:(NSIndexPath *)indexPath; )
@property (nonatomic, strong) NSArray* sections; <NITableViewModelSection> // Array of NITableViewModelSection
@property (nonatomic, strong) NSArray* sectionIndexTitles;
@property (nonatomic, strong) NSDictionary* sectionPrefixToSectionIndex;
pragma mark Creating Table View Cells
@property (nonatomic, weak) id<NITableViewModelDelegate> delegate;
if NS_BLOCKS_AVAILABLE
// If both the delegate and this block are provided, cells returned by this block will be used
// and the delegate will not be called.
@property (nonatomic, copy) NITableViewModelCellForIndexPathBlock createCellBlock;
//UITableViewDataSource
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section;
。。。。
//block和代理选用其一。。。。
-
(UITableViewCell *)tableView: (UITableView *)tableView
cellForRowAtIndexPath: (NSIndexPath *)indexPath {
id object = [self objectAtIndexPath:indexPath];UITableViewCell* cell = nil;
if NS_BLOCKS_AVAILABLE
if (nil != self.createCellBlock) {
cell = self.createCellBlock(tableView, indexPath, object);
}
endif
if (nil == cell) {
cell = [self.delegate tableViewModel:self
cellForTableView:tableView
atIndexPath:indexPath
withObject:object];
}
return cell;
}
主要的cell协议和基本数据类型
@protocol NICellObject <NSObject>
@required
- (Class)cellClass;
- (UITableViewCellStyle)cellStyle;
@protocol NINibCellObject <NSObject>
@required - (UINib *)cellNib;
- (Class)nibCellClass;
@interface NICellObject : NSObject <NICellObject>
// Designated initializer.
- (id)initWithCellClass:(Class)cellClass userInfo:(id)userInfo;
- (id)initWithCellClass:(Class)cellClass;
- (id)objectWithCellClass:(Class)cellClass userInfo:(id)userInfo;
- (id)objectWithCellClass:(Class)cellClass;
@property (nonatomic, strong) id userInfo;
@protocol NICell <NSObject>
-shouldUpdateCellWithObject
+shouldAppendObjectClassToReuseIdentifier
- (CGFloat)heightForObject:(id)object atIndexPath:(NSIndexPath *)indexPath tableView:
主cell工厂类目。它负责cell的产生。并兼顾刷新数据
@interface NICellFactory : NSObject <NITableViewModelDelegate>
NSMutableDictionary* objectToCellMap;
- (UITableViewCell *)tableViewModel:(NITableViewModel *)tableViewModel cellForTableView:(UITableView *)tableView atIndexPath:(NSIndexPath *)indexPath withObject:(id)object;
(void)mapObjectClass:(Class)objectClass toCellClass:(Class)cellClass;
(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath model:(NITableViewModel *)model;
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath model:(NITableViewModel *)model;
其主要流程是这样的。
定义代理action主体,通过设置代理类目NITableViewActions代理tableview的具体事件,同时指定本身为代理对象。
[[NITableViewActions alloc] initWithTarget:self]
可以覆盖实现。能够使封装和自定义不冲突。
期间行为关联是通过NIActions内部attach属性,存入了相关的字典、set内部,进行了捆绑操作。
其实这里也有些不足。基本细化控件的内部操作是个短板总觉得。。
数据源的定义是通过NITableViewModel初始化了NITableViewModelSection数据组信息,来进行相应的展示。
其中string默认设置
同时,它捆绑定义了NITableViewModelDelegate协议,
并提供了NICellFactory类辅工厂来辅助实现产生具体cell
产生
- (id)initWithCellClass:(Class)cellClass userInfo:(id)userInfo;
同时具体cell信息遵循NICell协议。来实现数据的更新操作
(id<NICell>)cell shouldUpdateCellWithObject:object
table.DataSource = NITableViewModel(初始化dataarray的sections:@[ NITableViewModelSection:header、footer、rows<cellObject> ] ,加载cell数据的delegate:NICellFactory< NITableViewModelDelegate>)
整体流程还算很简单吧。。因为具体控件的点击是它本身短板,所以使用的时候,这方面最好在它基础上做了一层封装,使开发更加的便捷简单。
cell高度自定义成了这样。方便在model中增加rowHeight变量,更方便获取cell高度 或者直接扩展ActionModel,但是此种方法需要获取内部变量forwarDelegate。有些危险。所以放弃了。。
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
CGFloat height = tableView.rowHeight;
id object = [(NITableViewModel )tableView.dataSource objectAtIndexPath:indexPath];
if (object && [object isKindOfClass:NICellObject.class]) {
if ([object respondsToSelector:@selector(rowHeight)]) {
SEL selector = NSSelectorFromString(@"rowHeight");
IMP imp = [object methodForSelector:selector];
float (func)(id , SEL) = (void *)imp;
float result = func(object , selector);
if (result != 0) {
return result;
}
}
}
id class = [object cellClass];
if ([class respondsToSelector:@selector(heightForObject:atIndexPath:tableView:)]) {
height = [class heightForObject:object atIndexPath:indexPath tableView:tableView];
}
return height;
}