Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for data sources with heterogeneous cell reuse identifiers #1

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Modify the solution to use a reuse identifier block to achieve less c…
…oupling
rafaelwinter committed May 21, 2014
commit 7648dc30bc9c2adb342f10a520d82e1837d6f55f
12 changes: 8 additions & 4 deletions TGRDataSource/TGRArrayDataSource.h
Original file line number Diff line number Diff line change
@@ -46,14 +46,18 @@ cellReuseIdentifier:(NSString *)reuseIdentifier
configureCellBlock:(TGRDataSourceCellBlock)configureCellBlock;

/**
Initializes the data source without a default cell reuse identifier.
Initializes the data source with a custom cell reuse identifier block.

@param items The items managed by the data source.
@param configureCellBlock A block that will be called when the view asks for a cell in a particular location.
@param reuseIdentifierBlock A block that will be called when the view asks for
the reuse identifier of cell in a particular location.
@param configureCellBlock A block that will be called when the view asks for a
cell in a particular location.

@return An initialized data source.
*/
- (id)initWithItems:(NSArray *)items
configureCellBlock:(TGRDataSourceCellBlock)configureCellBlock;
- (id)initWithItems:(NSArray *)items
reuseIdentifierBlock:(TGRDataSourceReuseIdentifierBlock)reuseIdentifierBlock
configureCellBlock:(TGRDataSourceCellBlock)configureCellBlock;

@end
17 changes: 11 additions & 6 deletions TGRDataSource/TGRArrayDataSource.m
Original file line number Diff line number Diff line change
@@ -28,7 +28,8 @@ - (id)initWithItems:(NSArray *)items
cellReuseIdentifier:(NSString *)reuseIdentifier
configureCellBlock:(TGRDataSourceCellBlock)configureCellBlock
{
self = [super initWithCellReuseIdentifier:reuseIdentifier configureCellBlock:configureCellBlock];
self = [super initWithCellReuseIdentifier:reuseIdentifier
configureCellBlock:configureCellBlock];

if (self) {
_items = [items copy];
@@ -37,12 +38,16 @@ - (id)initWithItems:(NSArray *)items
return self;
}

- (id)initWithItems:(NSArray *)items
configureCellBlock:(TGRDataSourceCellBlock)configureCellBlock
- (id)initWithItems:(NSArray *)items
reuseIdentifierBlock:(TGRDataSourceReuseIdentifierBlock)reuseIdentifierBlock
configureCellBlock:(TGRDataSourceCellBlock)configureCellBlock
{
self = [self initWithItems:items
cellReuseIdentifier:nil
configureCellBlock:configureCellBlock];
self = [super initWithReuseIdentifierBlock:reuseIdentifierBlock
configureCellBlock:configureCellBlock];

if (self) {
_items = [items copy];
}

return self;
}
34 changes: 15 additions & 19 deletions TGRDataSource/TGRDataSource.h
Original file line number Diff line number Diff line change
@@ -22,6 +22,7 @@

#import <UIKit/UIKit.h>

typedef NSString *(^TGRDataSourceReuseIdentifierBlock)(NSIndexPath *indexPath, id item);
typedef void (^TGRDataSourceCellBlock)(id cell, id item);

/**
@@ -35,6 +36,12 @@ typedef void (^TGRDataSourceCellBlock)(id cell, id item);
*/
@property (copy, nonatomic, readonly) NSString *cellReuseIdentifier;

/**
A block that will be called when the view asks for the reuse identifier of cell in a
particular location.
*/
@property (copy, nonatomic, readonly) TGRDataSourceReuseIdentifierBlock reuseIdentifierBlock;

/**
A block that will be called when the view asks for a cell in a particular location.
*/
@@ -57,34 +64,23 @@ typedef void (^TGRDataSourceCellBlock)(id cell, id item);
configureCellBlock:(TGRDataSourceCellBlock)configureCellBlock;

/**
Initializes the data source without a default cell reuse identifier.
Initializes the data source with a custom cell reuse identifier block.

@discussion This initializer considers the implementation of a table view or
collection view data source that provides heterogeneous cells. This implies
that the `cellReuseIdentifier` property will be ignored and the method
`reuseIdentifierForCellAtIndexPath:` must be overriden.
that the `cellReuseIdentifier` property will be ignored and the block
`reuseIdentifierBlock` will be used in it's place to determine the cell reuse
identifier .

@param reuseIdentifierBlock A block that will be called when the view asks for
the reuse identifier of cell in a particular location.
@param configureCellBlock A block that will be called when the view asks for a
cell in a particular location.

@return An initialized data source.
*/
- (id)initWithConfigureCellBlock:(TGRDataSourceCellBlock)configureCellBlock;

/**
Returns a reuse identifier used to dequeue a cell that will be placed
on a given location.

@discussion The default implementation of this method simply returns
the value of the `cellReuseIdentifier` property. Overriding this method allows
a subclass to use multiple reuse identifiers, which allows the creation
of table views and collection views composed by heterogeneous cell types.

@param indexPath The index path specifying the location of the cell.

@return A reuse identifier specific for that cell
*/
- (NSString *)reuseIdentifierForCellAtIndexPath:(NSIndexPath *)indexPath;
- (id)initWithReuseIdentifierBlock:(TGRDataSourceReuseIdentifierBlock)reuseIdentifierBlock
configureCellBlock:(TGRDataSourceCellBlock)configureCellBlock;

/**
Returns a data source item in a particular location.
28 changes: 16 additions & 12 deletions TGRDataSource/TGRDataSource.m
Original file line number Diff line number Diff line change
@@ -26,6 +26,7 @@
@interface TGRDataSource ()

@property (copy, nonatomic) NSString *cellReuseIdentifier;
@property (copy, nonatomic) TGRDataSourceReuseIdentifierBlock reuseIdentifierBlock;
@property (copy, nonatomic) TGRDataSourceCellBlock configureCellBlock;

@end
@@ -45,18 +46,19 @@ - (id)initWithCellReuseIdentifier:(NSString *)reuseIdentifier
return self;
}

- (id)initWithConfigureCellBlock:(TGRDataSourceCellBlock)configureCellBlock {
- (id)initWithReuseIdentifierBlock:(TGRDataSourceReuseIdentifierBlock)reuseIdentifierBlock
configureCellBlock:(TGRDataSourceCellBlock)configureCellBlock {

self = [self initWithCellReuseIdentifier:nil
configureCellBlock:configureCellBlock];

if (self) {
self.reuseIdentifierBlock = reuseIdentifierBlock;
}

return self;
}

- (NSString *)reuseIdentifierForCellAtIndexPath:(NSIndexPath *)indexPath {
[self subclassResponsibility:_cmd];
return nil;
}

- (id)itemAtIndexPath:(NSIndexPath *)indexPath {
[self subclassResponsibility:_cmd];
return nil;
@@ -77,14 +79,15 @@ - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
id item = [self itemAtIndexPath:indexPath];

NSString *reuseIdentifier = self.cellReuseIdentifier;
if (!reuseIdentifier) {
reuseIdentifier = [self reuseIdentifierForCellAtIndexPath:indexPath];
if (!reuseIdentifier && self.reuseIdentifierBlock) {
reuseIdentifier = self.reuseIdentifierBlock(indexPath, item);
}

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifier
forIndexPath:indexPath];
id item = [self itemAtIndexPath:indexPath];

if (self.configureCellBlock) {
self.configureCellBlock(cell, item);
@@ -105,14 +108,15 @@ - (NSInteger)collectionView:(UICollectionView *)collectionView
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
id item = [self itemAtIndexPath:indexPath];

NSString *reuseIdentifier = self.cellReuseIdentifier;
if (!reuseIdentifier) {
reuseIdentifier = [self reuseIdentifierForCellAtIndexPath:indexPath];
if (!reuseIdentifier && self.reuseIdentifierBlock) {
reuseIdentifier = self.reuseIdentifierBlock(indexPath, item);
}

UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier
forIndexPath:indexPath];
id item = [self itemAtIndexPath:indexPath];

if (self.configureCellBlock) {
self.configureCellBlock(cell, item);
9 changes: 7 additions & 2 deletions TGRDataSource/TGRFetchedResultsDataSource.h
Original file line number Diff line number Diff line change
@@ -39,7 +39,8 @@

@param controller The `NSFetchedResultsController` object managed by this data source.
@param reuseIdentifier The cell reuse identifier.
@param configureCellBlock A block that will be called when the view asks for a cell in a particular location.
@param configureCellBlock A block that will be called when the view asks for a cell in
a particular location.

@return An initialized data source.
*/
@@ -51,11 +52,15 @@
Initializes the data source without a default cell reuse identifier.

@param controller The `NSFetchedResultsController` object managed by this data source.
@param configureCellBlock A block that will be called when the view asks for a cell in a particular location.
@param reuseIdentifierBlock A block that will be called when the view asks for
the reuse identifier of cell in a particular location.
@param configureCellBlock A block that will be called when the view asks for a cell in
a particular location.

@return An initialized data source.
*/
- (id)initWithFetchedResultsController:(NSFetchedResultsController *)controller
reuseIdentifierBlock:(TGRDataSourceReuseIdentifierBlock)reuseIdentifierBlock
configureCellBlock:(TGRDataSourceCellBlock)configureCellBlock;

@end
10 changes: 7 additions & 3 deletions TGRDataSource/TGRFetchedResultsDataSource.m
Original file line number Diff line number Diff line change
@@ -38,11 +38,15 @@ - (id)initWithFetchedResultsController:(NSFetchedResultsController *)controller
}

- (id)initWithFetchedResultsController:(NSFetchedResultsController *)controller
reuseIdentifierBlock:(TGRDataSourceReuseIdentifierBlock)reuseIdentifierBlock
configureCellBlock:(TGRDataSourceCellBlock)configureCellBlock
{
self = [self initWithFetchedResultsController:controller
cellReuseIdentifier:nil
configureCellBlock:configureCellBlock];
self = [super initWithReuseIdentifierBlock:reuseIdentifierBlock
configureCellBlock:configureCellBlock];

if (self) {
_fetchedResultsController = controller;
}

return self;
}