Skip to content

Commit

Permalink
Merge pull request #95 from kettch/master
Browse files Browse the repository at this point in the history
Adding dequeue from Nib
  • Loading branch information
jwilling committed Jan 25, 2014
2 parents 4bdb151 + fdaa083 commit 67ad7af
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 5 deletions.
11 changes: 11 additions & 0 deletions JNWCollectionView/JNWCollectionViewFramework.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,20 @@ typedef NS_ENUM(NSInteger, JNWCollectionViewScrollPosition) {
/// The class passed in will be used to initialize a new instance of the view, as needed. The class
/// must be a subclass of JNWCollectionViewCell for the cell class, and JNWCollectionViewReusableView
/// for the supplementary view class, otherwise an exception will be thrown.
///
/// Registering a class or nib are exclusive: registering one will unregister the other.
- (void)registerClass:(Class)cellClass forCellWithReuseIdentifier:(NSString *)reuseIdentifier;
- (void)registerClass:(Class)supplementaryViewClass forSupplementaryViewOfKind:(NSString *)kind withReuseIdentifier:(NSString *)reuseIdentifier;

/// You can also register a nib instead of a class to be able to dequeue a cell or supplementary view.
///
/// The nib must contain a top-level object of a subclass of JNWCollectionViewCell for the cell, and
/// JNWCollectionViewReusableView for the supplementary view, otherwise an exception will be thrown when dequeuing.
///
/// Registering a class or nib are exclusive: registering one will unregister the other.
- (void)registerNib:(NSNib *)cellNib forCellWithReuseIdentifier:(NSString *)identifier;
- (void)registerNib:(NSNib *)supplementaryViewNib forSupplementaryViewOfKind:(NSString *)kind withReuseIdentifier:(NSString *)reuseIdentifier;

/// These methods are used to create or reuse a new view. Cells should not be created manually. Instead,
/// these methods should be called with a reuse identifier previously registered using
/// -registerClass:forCellWithReuseIdentifier: or -registerClass:forSupplementaryViewOfKind:withReuseIdentifier:.
Expand Down
62 changes: 57 additions & 5 deletions JNWCollectionView/JNWCollectionViewFramework.m
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,13 @@ @interface JNWCollectionView() {
@property (nonatomic, strong) NSMutableDictionary *reusableCells; // { identifier : (cells) }
@property (nonatomic, strong) NSMutableDictionary *visibleCellsMap; // { index path : cell }
@property (nonatomic, strong) NSMutableDictionary *cellClassMap; // { identifier : class }
@property (nonatomic, strong) NSMutableDictionary *cellNibMap; // { identifier : nib }

// Supplementary views
@property (nonatomic, strong) NSMutableDictionary *reusableSupplementaryViews; // { "kind/identifier" : (views) }
@property (nonatomic, strong) NSMutableDictionary *visibleSupplementaryViewsMap; // { "index/kind/identifier" : view } }
@property (nonatomic, strong) NSMutableDictionary *supplementaryViewClassMap; // { "kind/identifier" : class }
@property (nonatomic, strong) NSMutableDictionary *supplementaryViewNibMap; // { "kind/identifier" : nib }

@end

Expand All @@ -84,9 +86,11 @@ static void JNWCollectionViewCommonInit(JNWCollectionView *collectionView) {

collectionView.selectedIndexes = [NSMutableArray array];
collectionView.cellClassMap = [NSMutableDictionary dictionary];
collectionView.cellNibMap = [NSMutableDictionary dictionary];
collectionView.visibleCellsMap = [NSMutableDictionary dictionary];
collectionView.reusableCells = [NSMutableDictionary dictionary];
collectionView.supplementaryViewClassMap = [NSMutableDictionary dictionary];
collectionView.supplementaryViewNibMap = [NSMutableDictionary dictionary];
collectionView.visibleSupplementaryViewsMap = [NSMutableDictionary dictionary];
collectionView.reusableSupplementaryViews = [NSMutableDictionary dictionary];

Expand Down Expand Up @@ -155,6 +159,7 @@ - (void)registerClass:(Class)cellClass forCellWithReuseIdentifier:(NSString *)re
NSParameterAssert(reuseIdentifier);
NSAssert([cellClass isSubclassOfClass:JNWCollectionViewCell.class], @"registered cell class must be a subclass of JNWCollectionViewCell");
self.cellClassMap[reuseIdentifier] = cellClass;
[self.cellNibMap removeObjectForKey:reuseIdentifier];
}

- (void)registerClass:(Class)supplementaryViewClass forSupplementaryViewOfKind:(NSString *)kind withReuseIdentifier:(NSString *)reuseIdentifier {
Expand All @@ -168,6 +173,25 @@ - (void)registerClass:(Class)supplementaryViewClass forSupplementaryViewOfKind:(
// form the key for the supplementary views.
NSString *identifier = [self supplementaryViewIdentifierWithKind:kind reuseIdentifier:reuseIdentifier];
self.supplementaryViewClassMap[identifier] = supplementaryViewClass;
[self.supplementaryViewNibMap removeObjectForKey:identifier];
}

- (void)registerNib:(NSNib *)cellNib forCellWithReuseIdentifier:(NSString *)reuseIdentifier {
NSParameterAssert(cellNib);
NSParameterAssert(reuseIdentifier);

self.cellNibMap[reuseIdentifier] = cellNib;
[self.cellClassMap removeObjectForKey:reuseIdentifier];
}

- (void)registerNib:(NSNib *)supplementaryViewNib forSupplementaryViewOfKind:(NSString *)kind withReuseIdentifier:(NSString *)reuseIdentifier {
NSParameterAssert(supplementaryViewNib);
NSParameterAssert(kind);
NSParameterAssert(reuseIdentifier);

NSString *identifier = [self supplementaryViewIdentifierWithKind:kind reuseIdentifier:reuseIdentifier];
self.supplementaryViewNibMap[identifier] = supplementaryViewNib;
[self.supplementaryViewClassMap removeObjectForKey:identifier];
}

- (id)dequeueItemWithIdentifier:(NSString *)identifier inReusePool:(NSDictionary *)reuse {
Expand Down Expand Up @@ -200,6 +224,24 @@ - (void)enqueueItem:(id)item withIdentifier:(NSString *)identifier inReusePool:(
[reusableCells addObject:item];
}

- (id)firstTopLevelObjectOfClass:(Class)objectClass inNib:(NSNib *)nib {
id foundObject = nil;
NSArray *topLevelObjects = nil;
if([nib instantiateWithOwner:self topLevelObjects:&topLevelObjects]) {
NSUInteger objectIndex = [topLevelObjects indexOfObjectPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
if ([obj isKindOfClass:objectClass]) {
*stop = YES;
return YES;
}
return NO;
}];
if (objectIndex != NSNotFound) {
foundObject = [topLevelObjects objectAtIndex:objectIndex];
}
}
return foundObject;
}

- (JNWCollectionViewCell *)dequeueReusableCellWithIdentifier:(NSString *)identifier {
NSParameterAssert(identifier);
JNWCollectionViewCell *cell = [self dequeueItemWithIdentifier:identifier inReusePool:self.reusableCells];
Expand All @@ -208,12 +250,17 @@ - (JNWCollectionViewCell *)dequeueReusableCellWithIdentifier:(NSString *)identif
// for this identifier, we use it, otherwise we just create an instance of JNWCollectionViewCell.
if (cell == nil) {
Class cellClass = self.cellClassMap[identifier];

if (cellClass == nil) {
NSNib *cellNib = self.cellNibMap[identifier];

if (cellClass == nil && cellNib == nil) {
cellClass = JNWCollectionViewCell.class;
}

cell = [[cellClass alloc] initWithFrame:CGRectZero];
if (cellNib != nil) {
cell = [self firstTopLevelObjectOfClass:JNWCollectionViewCell.class inNib:cellNib];
} else if (cellClass != nil) {
cell = [[cellClass alloc] initWithFrame:CGRectZero];
}
}

cell.reuseIdentifier = identifier;
Expand All @@ -230,12 +277,17 @@ - (JNWCollectionViewReusableView *)dequeueReusableSupplementaryViewOfKind:(NSStr

if (view == nil) {
Class viewClass = self.supplementaryViewClassMap[identifier];
NSNib *viewNib = self.supplementaryViewNibMap[identifier];

if (viewClass == nil) {
if (viewClass == nil && viewNib == nil) {
viewClass = JNWCollectionViewReusableView.class;
}

view = [[viewClass alloc] initWithFrame:CGRectZero];
if (viewNib != nil) {
view = [self firstTopLevelObjectOfClass:JNWCollectionViewReusableView.class inNib:viewNib];
} else if (viewClass != nil) {
view = [[viewClass alloc] initWithFrame:CGRectZero];
}
}

view.reuseIdentifier = reuseIdentifier;
Expand Down

0 comments on commit 67ad7af

Please sign in to comment.