SSDataSources 0.8.6

SSDataSources 0.8.6

测试已测试
语言语言 Obj-CObjective C
许可证 MIT
发布最后发布2017年1月

Jonathan HershSamuel GiddinsKevin Morton维护。



Circle CI Coverage Status

为您的UITableViewUICollectionView提供灵活的数据源。哇,许多DRY

毫无疑问,您已经在之前多次执行了tableView:cellForRowAtIndexPath:tableView:numberOfRowsInSection:,以及collectionView:cellForItemAtIndexPath:collectionView:numberOfItemsInSection:程序。您也可能已经更新了数据,但忘记了更新表格或收藏视图。哎呀 -- 崩溃!有没有更好的方法?

SSDataSources是一系列符合UITableViewDataSourceUICollectionViewDataSource的对象。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.hSSSection.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

核心数据

作为一个现代的互联网人,有时候你希望呈现一个由核心数据获取请求或获取结果控制器支持得UITableViewUICollectionView。这里展示了SSDataSourcesSSCoreDataSource特性,它由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制作的 -- ( | @jhersh)