diff --git a/AsyncDisplayKit/Details/ASDataController.mm b/AsyncDisplayKit/Details/ASDataController.mm index 7c3bf0e8f3..f1d420334a 100644 --- a/AsyncDisplayKit/Details/ASDataController.mm +++ b/AsyncDisplayKit/Details/ASDataController.mm @@ -178,9 +178,7 @@ static void *kASSizingQueueContext = &kASSizingQueueContext; dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_apply(batchCount, queue, ^(size_t i) { unsigned long k = j + i; - ASIndexedNodeContext *context = contexts[k]; - ASCellNodeBlock nodeBlock = context.nodeBlock; - ASCellNode *node = nodeBlock(); + ASCellNode *node = [contexts[k] allocateNode]; ASDisplayNodeAssertNotNil(node, @"Node block created nil node"); allocatedNodeBuffer[i] = node; }); @@ -422,8 +420,8 @@ static void *kASSizingQueueContext = &kASSizingQueueContext; [self accessDataSourceSynchronously:synchronously withBlock:^{ NSUInteger sectionCount = [_dataSource numberOfSectionsInDataController:self]; - NSMutableArray *contexts = [NSMutableArray array]; - [self _populateFromEntireDataSourceWithMutableContexts:contexts]; + NSIndexSet *sectionIndexSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, sectionCount)]; + NSArray *contexts = [self _populateFromDataSourceWithSectionIndexSet:sectionIndexSet]; // Allow subclasses to perform setup before going into the edit transaction [self prepareForReloadData]; @@ -441,13 +439,12 @@ static void *kASSizingQueueContext = &kASSizingQueueContext; [self willReloadData]; - // Insert each section + // Insert empty sections NSMutableArray *sections = [NSMutableArray arrayWithCapacity:sectionCount]; for (int i = 0; i < sectionCount; i++) { [sections addObject:[[NSMutableArray alloc] init]]; } - - [self _insertSections:sections atIndexSet:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, sectionCount)] withAnimationOptions:animationOptions]; + [self _insertSections:sections atIndexSet:sectionIndexSet withAnimationOptions:animationOptions]; [self _batchLayoutNodesFromContexts:contexts withAnimationOptions:animationOptions]; @@ -494,11 +491,10 @@ static void *kASSizingQueueContext = &kASSizingQueueContext; /** * Fetches row contexts for the provided sections from the data source. - * - * @discussion Results are stored in the passed mutable arrays. */ -- (void)_populateFromDataSourceWithSectionIndexSet:(NSIndexSet *)indexSet mutableContexts:(NSMutableArray *)contexts +- (NSArray *)_populateFromDataSourceWithSectionIndexSet:(NSIndexSet *)indexSet { + NSMutableArray *contexts = [NSMutableArray array]; [indexSet enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) { NSUInteger rowNum = [_dataSource dataController:self rowsInSection:idx]; NSIndexPath *sectionIndex = [[NSIndexPath alloc] initWithIndex:idx]; @@ -511,31 +507,9 @@ static void *kASSizingQueueContext = &kASSizingQueueContext; constrainedSize:constrainedSize]]; } }]; + return contexts; } -/** - * Fetches row contexts for all sections from the data source. - * - * @discussion Results are stored in the passed mutable arrays. - */ -- (void)_populateFromEntireDataSourceWithMutableContexts:(NSMutableArray *)contexts -{ - NSUInteger sectionNum = [_dataSource numberOfSectionsInDataController:self]; - for (NSUInteger i = 0; i < sectionNum; i++) { - NSIndexPath *sectionIndexPath = [[NSIndexPath alloc] initWithIndex:i]; - NSUInteger rowNum = [_dataSource dataController:self rowsInSection:i]; - for (NSUInteger j = 0; j < rowNum; j++) { - NSIndexPath *indexPath = [sectionIndexPath indexPathByAddingIndex:j]; - ASCellNodeBlock nodeBlock = [_dataSource dataController:self nodeBlockAtIndexPath:indexPath]; - ASSizeRange constrainedSize = [self constrainedSizeForNodeOfKind:ASDataControllerRowNodeKind atIndexPath:indexPath]; - [contexts addObject:[[ASIndexedNodeContext alloc] initWithNodeBlock:nodeBlock - indexPath:indexPath - constrainedSize:constrainedSize]]; - } - } -} - - #pragma mark - Batching (External API) - (void)beginUpdates @@ -617,8 +591,7 @@ static void *kASSizingQueueContext = &kASSizingQueueContext; [_editingTransactionQueue waitUntilAllOperationsAreFinished]; [self accessDataSourceWithBlock:^{ - NSMutableArray *contexts = [NSMutableArray array]; - [self _populateFromDataSourceWithSectionIndexSet:sections mutableContexts:contexts]; + NSArray *contexts = [self _populateFromDataSourceWithSectionIndexSet:sections]; [self prepareForInsertSections:sections]; @@ -668,8 +641,7 @@ static void *kASSizingQueueContext = &kASSizingQueueContext; [_editingTransactionQueue waitUntilAllOperationsAreFinished]; [self accessDataSourceWithBlock:^{ - NSMutableArray *contexts = [NSMutableArray array]; - [self _populateFromDataSourceWithSectionIndexSet:sections mutableContexts:contexts]; + NSArray *contexts= [self _populateFromDataSourceWithSectionIndexSet:sections]; [self prepareForReloadSections:sections]; diff --git a/AsyncDisplayKit/Details/ASIndexedNodeContext.h b/AsyncDisplayKit/Details/ASIndexedNodeContext.h index 74263172fc..ed1d2f49ba 100644 --- a/AsyncDisplayKit/Details/ASIndexedNodeContext.h +++ b/AsyncDisplayKit/Details/ASIndexedNodeContext.h @@ -7,11 +7,9 @@ // #import -#import @interface ASIndexedNodeContext : NSObject -@property (nonatomic, readonly, strong) ASCellNodeBlock nodeBlock; @property (nonatomic, readonly, strong) NSIndexPath *indexPath; @property (nonatomic, readonly, assign) ASSizeRange constrainedSize; @@ -19,4 +17,9 @@ indexPath:(NSIndexPath *)indexPath constrainedSize:(ASSizeRange)constrainedSize; +/** + * Returns a node allocated by executing node block. Node block will be nil out immediately. + */ +- (ASCellNode *)allocateNode; + @end diff --git a/AsyncDisplayKit/Details/ASIndexedNodeContext.m b/AsyncDisplayKit/Details/ASIndexedNodeContext.m index f7ec9571ea..b6038137d6 100644 --- a/AsyncDisplayKit/Details/ASIndexedNodeContext.m +++ b/AsyncDisplayKit/Details/ASIndexedNodeContext.m @@ -8,12 +8,20 @@ #import "ASIndexedNodeContext.h" +@interface ASIndexedNodeContext () + +/// Required node block used to allocate a cell node. Nil after the first execution. +@property (nonatomic, strong) ASCellNodeBlock nodeBlock; + +@end + @implementation ASIndexedNodeContext - (instancetype)initWithNodeBlock:(ASCellNodeBlock)nodeBlock indexPath:(NSIndexPath *)indexPath constrainedSize:(ASSizeRange)constrainedSize; { + NSAssert(nodeBlock != nil && indexPath != nil, @"Node block and index path must not be nil"); self = [super init]; if (self) { _nodeBlock = nodeBlock; @@ -23,4 +31,12 @@ return self; } +- (ASCellNode *)allocateNode +{ + NSAssert(_nodeBlock != nil, @"Node block is gone. Should not execute it more than once"); + ASCellNode *node = _nodeBlock(); + _nodeBlock = nil; + return node; +} + @end