测试已测试 | ✓ |
语言语言 | Obj-CObjective C |
许可证 | MIT |
发布最后发布 | 2017年1月 |
由Jonathan Hersh、Samuel Giddins、Kevin Morton维护。
为您的UITableView
和UICollectionView
提供灵活的数据源。哇,许多DRY
毫无疑问,您已经在之前多次执行了tableView:cellForRowAtIndexPath:
和tableView:numberOfRowsInSection:
,以及collectionView:cellForItemAtIndexPath:
和collectionView:numberOfItemsInSection:
程序。您也可能已经更新了数据,但忘记了更新表格或收藏视图。哎呀 -- 崩溃!有没有更好的方法?
SSDataSources
是一系列符合UITableViewDataSource
和UICollectionViewDataSource
的对象。SSBaseDataSource
是一个抽象的超类,定义了一个公共接口,该接口由四个具体的子类实现
SSArrayDataSource
为单节表格或收藏视图提供动力。SSSectionedDataSource
为多节表格或收藏视图提供动力。SSCoreDataSource
为后端为Core Data查询请求的表格或收藏视图提供动力。SSExpandingDataSource
为多节表格或收藏视图提供动力,类似于SSSectionedDataSource
,但还允许展开和折叠节。SSDataSources
是我自己对objc.io的精彩第一期中提出的一些想法的实现。
SSDataSources
在我的应用程序MUDRammer - 适用于iPhone和iPad的现代MUD客户端中提供单节、多节和Core Data支持的表格。
使用CocoaPods进行安装。将其添加到您的Podfile
pod 'SSDataSources', :head # YOLO
在Example
项目中的所有表格和收藏视图都是使用SSDataSources
构建的。
pod try SSDataSources
或者
cd Example
pod install
open ExampleSSDataSources.xcworkspace
SSArrayDataSource
为单节表格或收藏视图提供动力。有关详细信息,请参阅SSArrayDataSource.h
。
请查看示例项目,其中包含使用数组数据源的示例表格和收藏视图。
SSArrayDataSource
还可以观察到数组的特定目标键路径。
@interface WizardicTableViewController : UITableViewController
@property (nonatomic, strong) SSArrayDataSource *wizardDataSource;
@end
@implementation WizardicTableViewController
- (void)viewDidLoad {
[super viewDidLoad];
_wizardDataSource = [[SSArrayDataSource alloc] initWithItems:
@[ @"Merlyn", @"Gandalf", @"Melisandre" ]];
// SSDataSources creates your cell and calls
// this configure block for each cell with
// the object being presented in that cell,
// the parent table or collection view,
// and the index path at which the cell appears.
self.wizardDataSource.cellConfigureBlock = ^(SSBaseTableCell *cell,
NSString *wizard,
UITableView *tableView,
NSIndexPath *indexPath) {
cell.textLabel.text = wizard;
};
self.wizardDataSource.tableActionBlock = ^BOOL(SSCellActionType action,
UITableView *tableView,
NSIndexPath *indexPath) {
// Disallow gestures for moving and editing.
// You could instead do something like allowing only editing:
// return action == SSCellActionTypeEdit;
return NO;
};
// Set the tableView property and the data source will perform
// insert/reload/delete calls on the table as its data changes.
// This also assigns the table's `dataSource` property.
self.wizardDataSource.tableView = self.tableView;
}
@end
到此为止 - 你完成了!
也许您的数据已更改
// Sometimes it's nice to add a view that automatically
// shows when the data source is empty and
// hides when the data source has items.
UILabel *noItemsLabel = [UILabel new];
noItemsLabel.text = @"No Items";
noItemsLabel.font = [UIFont boldSystemFontOfSize:18.0f];
noItemsLabel.textAlignment = NSTextAlignmentCenter;
self.wizardDataSource.emptyView = noItemsLabel;
// Optional - row animation for table updates.
self.wizardDataSource.rowAnimation = UITableViewRowAnimationFade;
// Automatically inserts two new cells at the end of the table.
[self.wizardDataSource appendItems:@[ @"Saruman", @"Alatar" ]];
// Update the fourth item; reloads the fourth row.
[self.wizardDataSource replaceItemAtIndex:3 withItem:@"Pallando"];
// Sorry Merlyn :(
[self.wizardDataSource moveItemAtIndex:0 toIndex:1];
// Remove the second and third cells.
[self.wizardDataSource removeItemsInRange:NSMakeRange( 1, 2 )];
也许您有自定义的表格单元类或同一表格中的多个类
self.wizardDataSource.cellCreationBlock = ^id(NSString *wizard,
UITableView *tableView,
NSIndexPath *indexPath) {
if ([wizard isEqualToString:@"Gandalf"]) {
return [MiddleEarthWizardCell cellForTableView:tableView];
} else if ([wizard isEqualToString:@"Merlyn"]) {
return [ArthurianWizardCell cellForTableView:tableView];
}
};
您的视图控制器应继续实现UITableViewDelegate
。在这里,SSDataSources
也能提供帮助
- (void)tableView:(UITableView *)tv didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *wizard = [self.wizardDataSource itemAtIndexPath:indexPath];
// do something with `wizard`
}
- (CGFloat)tableView:(UITableView *)tv heightForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *wizard = [self.wizardDataSource itemAtIndexPath:indexPath];
// Calculate and return a height for `wizard`.
// You might do something like...
return [wizard boundingRectWithSize:CGSizeMake(CGRectGetWidth(tv), CGFLOAT_MAX)
options:NSStringDrawingUsesLineFragmentOrigin
attributes:@{ NSFontAttributeName : [UIFont boldSystemFontOfSize:14] }
context:NULL].height;
}
SSSectionedDataSource
为表格或集合视图提供支持,可以包含多个区域。每个区域由一个SSSection
对象来模型化,该对象存储区域的项目和其他一些可配置的元素。更多信息请参见SSSectionedDataSource.h
和SSSection.h
。
查看示例项目以获取使用分节数据源的表格示例。
@interface ElementalTableViewController : UITableViewController
@property (nonatomic, strong) SSSectionedDataSource *elementDataSource;
@end
@implementation ElementalTableViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Let's start with one section
_elementDataSource = [[SSSectionedDataSource alloc] initWithItems:@[ @"Earth" ]];
self.elementDataSource.cellConfigureBlock = ^(SSBaseTableCell *cell,
NSString *element,
UITableView *tableView,
NSIndexPath *indexPath) {
cell.textLabel.text = element;
};
// Setting the tableView property automatically updates
// the table in response to data changes.
// This also sets the table's `dataSource` property.
self.elementDataSource.tableView = self.tableView;
}
@end
SSSectionedDataSource
涵盖了数据变化的情况。
// Sometimes it's nice to add a view that automatically
// shows when the data source is empty and
// hides when the data source has items.
UILabel *noItemsLabel = [UILabel new];
noItemsLabel.text = @"No Items";
noItemsLabel.font = [UIFont boldSystemFontOfSize:18.0f];
noItemsLabel.textAlignment = NSTextAlignmentCenter;
self.elementDataSource.emptyView = noItemsLabel;
// Animation for table updates
self.elementDataSource.rowAnimation = UITableViewRowAnimationFade;
// Add some new sections
[self.elementDataSource appendSection:[SSSection sectionWithItems:@[ @"Fire" ]]];
[self.elementDataSource appendSection:[SSSection sectionWithItems:@[ @"Wind" ]]];
[self.elementDataSource appendSection:[SSSection sectionWithItems:@[ @"Water" ]]];
[self.elementDataSource appendSection:[SSSection sectionWithItems:@[ @"Heart", @"GOOOO PLANET!" ]]];
// Are you 4 srs, heart?
[self.elementDataSource removeSectionAtIndex:([elementDataSource numberOfSections] - 1)];
SSExpandingDataSource
为多节表格或收藏视图提供动力,类似于SSSectionedDataSource
,但还允许展开和折叠节。
可以切换任意数量的区域开关,以打开或关闭它们。当区域折叠时,不同的区域可以显示不同数量的行。
查看示例项目以获取使用扩展数据源的表格示例。
@interface ExpandingTableViewController : UITableViewController
@property (nonatomic, strong) SSExpandingDataSource *dataSource;
@end
@implementation ExpandingTableViewController
- (void)viewDidLoad {
[super viewDidLoad];
_dataSource = [[SSExpandingDataSource alloc] initWithItems:@[ @1, @2, @3 ]];
[self.dataSource appendSection:[SSSection sectionWithItems:@[ @4, @5, @6 ]]];
self.dataSource.cellConfigureBlock = ^(SSBaseTableCell *cell,
NSNumber *number,
UITableView *tableView,
NSIndexPath *indexPath) {
cell.textLabel.text = [number stringValue];
};
self.dataSource.collapsedSectionCountBlock = ^NSInteger(SSSection *section,
NSInteger sectionIndex) {
// Each section can show different numbers of rows when collapsed.
// Here, sections collapse down to 1 row more than their index in the table.
// Section 0 collapses to 1 row, section 1 collapses to 2 rows...
return 1 + sectionIndex;
};
// Setting the tableView property automatically updates
// the table in response to data changes.
// This also sets the table's `dataSource` property.
self.dataSource.tableView = self.tableView;
// Collapse the second section.
// You could also do this in response to a touch or any other event.
[self.dataSource setSectionAtIndex:1 expanded:NO];
}
@end
作为一个现代的互联网人,有时候你希望呈现一个由核心数据获取请求或获取结果控制器支持得UITableView
或UICollectionView
。这里展示了SSDataSources
的SSCoreDataSource
特性,它由MagicalRecord客串。
@interface SSCoreDataTableViewController : UITableViewController
@property (nonatomic, strong) SSCoreDataSource *dataSource;
@end
@implementation SSCoreDataTableViewController
- (void) viewDidLoad {
[super viewDidLoad];
NSFetchRequest *triggerFetch = [Trigger MR_requestAllSortedBy:[Trigger defaultSortField]
ascending:[Trigger defaultSortAscending]];
_dataSource = [[SSCoreDataSource alloc] initWithFetchRequest:triggerFetch
inContext:[NSManagedObjectContext
MR_defaultContext]
sectionNameKeyPath:nil];
self.dataSource.cellConfigureBlock = ^(SSBaseTableCell *cell,
Trigger *trigger,
UITableView *tableView,
NSIndexPath *indexPath ) {
cell.textLabel.text = trigger.name;
};
// SSCoreDataSource conforms to NSFetchedResultsControllerDelegate.
// Set the `tableView` property to automatically update the table
// after changes in the data source's managed object context.
// This also sets the tableview's `dataSource`.
self.dataSource.tableView = self.tableView;
// Optional - row animation to use for update events.
self.dataSource.rowAnimation = UITableViewRowAnimationFade;
// Optional - permissions for editing and moving
self.dataSource.tableActionBlock = ^BOOL(SSCellActionType actionType,
UITableView *tableView,
NSIndexPath *indexPath) {
// Disallow moving, allow editing
return actionType == SSCellActionTypeEdit;
};
// Optional - handle managed object deletion
self.dataSource.tableDeletionBlock = ^(SSCoreDataSource *aDataSource,
UITableView *tableView,
NSIndexPath *indexPath) {
Trigger *myObject = [aDataSource itemAtIndexPath:indexPath];
// SSCoreDataSource conforms to NSFetchedResultsControllerDelegate,
// so saving the object's context will automatically update the table.
[myObject deleteInContext:myObject.managedObjectContext];
[myObject.managedObjectContext MR_saveToPersistentStoreWithCompletion:nil];
};
}
@end
SSDataSources
是由@jhersh制作的 -- (electronic email | @jhersh)