diff --git a/AsyncDisplayKit/AsyncDisplayKit-iOS.h b/AsyncDisplayKit-iOS/AsyncDisplayKit-iOS.h similarity index 60% rename from AsyncDisplayKit/AsyncDisplayKit-iOS.h rename to AsyncDisplayKit-iOS/AsyncDisplayKit-iOS.h index 3e2ec7f449..130cb0da8a 100644 --- a/AsyncDisplayKit/AsyncDisplayKit-iOS.h +++ b/AsyncDisplayKit-iOS/AsyncDisplayKit-iOS.h @@ -5,12 +5,15 @@ * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. */ + #import //! Project version number for AsyncDisplayKit-iOS. -FOUNDATION_EXPORT double AsyncDisplayKitVersionNumber; +FOUNDATION_EXPORT double AsyncDisplayKit_iOSVersionNumber; //! Project version string for AsyncDisplayKit-iOS. -FOUNDATION_EXPORT const unsigned char AsyncDisplayKitVersionString[]; +FOUNDATION_EXPORT const unsigned char AsyncDisplayKit_iOSVersionString[]; + +// In this header, you should import all the public headers of your framework using statements like #import + -#import \ No newline at end of file diff --git a/AsyncDisplayKit/Info.plist b/AsyncDisplayKit-iOS/Info.plist similarity index 100% rename from AsyncDisplayKit/Info.plist rename to AsyncDisplayKit-iOS/Info.plist diff --git a/AsyncDisplayKit.podspec b/AsyncDisplayKit.podspec index daa77e83e1..7341bf3bac 100644 --- a/AsyncDisplayKit.podspec +++ b/AsyncDisplayKit.podspec @@ -26,7 +26,10 @@ Pod::Spec.new do |spec| # ASDealloc2MainObject must be compiled with MRR spec.requires_arc = true - spec.exclude_files = ['AsyncDisplayKit/Details/ASDealloc2MainObject.m'] + spec.exclude_files = [ + 'AsyncDisplayKit/Details/ASDealloc2MainObject.h', + 'AsyncDisplayKit/Details/ASDealloc2MainObject.m', + ] spec.subspec 'ASDealloc2MainObject' do |mrr| mrr.requires_arc = false mrr.source_files = [ diff --git a/AsyncDisplayKit.xcodeproj/xcshareddata/xcschemes/AsyncDisplayKit-iOS.xcscheme b/AsyncDisplayKit.xcodeproj/xcshareddata/xcschemes/AsyncDisplayKit-iOS.xcscheme index d46a787376..2a1226a3f6 100644 --- a/AsyncDisplayKit.xcodeproj/xcshareddata/xcschemes/AsyncDisplayKit-iOS.xcscheme +++ b/AsyncDisplayKit.xcodeproj/xcshareddata/xcschemes/AsyncDisplayKit-iOS.xcscheme @@ -14,7 +14,7 @@ buildForAnalyzing = "YES"> @@ -42,7 +42,7 @@ @@ -60,7 +60,7 @@ diff --git a/AsyncDisplayKit/ASCollectionView.mm b/AsyncDisplayKit/ASCollectionView.mm index 08f6608fd8..36a995f90b 100644 --- a/AsyncDisplayKit/ASCollectionView.mm +++ b/AsyncDisplayKit/ASCollectionView.mm @@ -184,7 +184,7 @@ static BOOL _isInterceptedSelector(SEL sel) ASDisplayNodePerformBlockOnMainThread(^{ [super reloadData]; }); - [_dataController reloadDataWithAnimationOption:kASCollectionViewAnimationNone completion:completion]; + [_dataController reloadDataWithAnimationOptions:kASCollectionViewAnimationNone completion:completion]; } - (void)reloadData @@ -290,42 +290,42 @@ static BOOL _isInterceptedSelector(SEL sel) - (void)insertSections:(NSIndexSet *)sections { - [_dataController insertSections:sections withAnimationOption:kASCollectionViewAnimationNone]; + [_dataController insertSections:sections withAnimationOptions:kASCollectionViewAnimationNone]; } - (void)deleteSections:(NSIndexSet *)sections { - [_dataController deleteSections:sections withAnimationOption:kASCollectionViewAnimationNone]; + [_dataController deleteSections:sections withAnimationOptions:kASCollectionViewAnimationNone]; } - (void)reloadSections:(NSIndexSet *)sections { - [_dataController reloadSections:sections withAnimationOption:kASCollectionViewAnimationNone]; + [_dataController reloadSections:sections withAnimationOptions:kASCollectionViewAnimationNone]; } - (void)moveSection:(NSInteger)section toSection:(NSInteger)newSection { - [_dataController moveSection:section toSection:newSection withAnimationOption:kASCollectionViewAnimationNone]; + [_dataController moveSection:section toSection:newSection withAnimationOptions:kASCollectionViewAnimationNone]; } - (void)insertItemsAtIndexPaths:(NSArray *)indexPaths { - [_dataController insertRowsAtIndexPaths:indexPaths withAnimationOption:kASCollectionViewAnimationNone]; + [_dataController insertRowsAtIndexPaths:indexPaths withAnimationOptions:kASCollectionViewAnimationNone]; } - (void)deleteItemsAtIndexPaths:(NSArray *)indexPaths { - [_dataController deleteRowsAtIndexPaths:indexPaths withAnimationOption:kASCollectionViewAnimationNone]; + [_dataController deleteRowsAtIndexPaths:indexPaths withAnimationOptions:kASCollectionViewAnimationNone]; } - (void)reloadItemsAtIndexPaths:(NSArray *)indexPaths { - [_dataController reloadRowsAtIndexPaths:indexPaths withAnimationOption:kASCollectionViewAnimationNone]; + [_dataController reloadRowsAtIndexPaths:indexPaths withAnimationOptions:kASCollectionViewAnimationNone]; } - (void)moveItemAtIndexPath:(NSIndexPath *)indexPath toIndexPath:(NSIndexPath *)newIndexPath { - [_dataController moveRowAtIndexPath:indexPath toIndexPath:newIndexPath withAnimationOption:kASCollectionViewAnimationNone]; + [_dataController moveRowAtIndexPath:indexPath toIndexPath:newIndexPath withAnimationOptions:kASCollectionViewAnimationNone]; } - (ASCellNode *)nodeForItemAtIndexPath:(NSIndexPath *)indexPath @@ -574,7 +574,7 @@ static BOOL _isInterceptedSelector(SEL sel) return [_dataController nodesAtIndexPaths:indexPaths]; } -- (void)rangeController:(ASRangeController *)rangeController didInsertNodesAtIndexPaths:(NSArray *)indexPaths withAnimationOption:(ASDataControllerAnimationOptions)animationOption +- (void)rangeController:(ASRangeController *)rangeController didInsertNodesAtIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions { ASDisplayNodeAssertMainThread(); if (_performingBatchUpdates) { @@ -588,7 +588,7 @@ static BOOL _isInterceptedSelector(SEL sel) } } -- (void)rangeController:(ASRangeController *)rangeController didDeleteNodesAtIndexPaths:(NSArray *)indexPaths withAnimationOption:(ASDataControllerAnimationOptions)animationOption +- (void)rangeController:(ASRangeController *)rangeController didDeleteNodesAtIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions { ASDisplayNodeAssertMainThread(); @@ -603,7 +603,7 @@ static BOOL _isInterceptedSelector(SEL sel) } } -- (void)rangeController:(ASRangeController *)rangeController didInsertSectionsAtIndexSet:(NSIndexSet *)indexSet withAnimationOption:(ASDataControllerAnimationOptions)animationOption +- (void)rangeController:(ASRangeController *)rangeController didInsertSectionsAtIndexSet:(NSIndexSet *)indexSet withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions { ASDisplayNodeAssertMainThread(); @@ -618,7 +618,7 @@ static BOOL _isInterceptedSelector(SEL sel) } } -- (void)rangeController:(ASRangeController *)rangeController didDeleteSectionsAtIndexSet:(NSIndexSet *)indexSet withAnimationOption:(ASDataControllerAnimationOptions)animationOption +- (void)rangeController:(ASRangeController *)rangeController didDeleteSectionsAtIndexSet:(NSIndexSet *)indexSet withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions { ASDisplayNodeAssertMainThread(); diff --git a/AsyncDisplayKit/ASDisplayNode.mm b/AsyncDisplayKit/ASDisplayNode.mm index a46a54fc7a..cf4959662c 100644 --- a/AsyncDisplayKit/ASDisplayNode.mm +++ b/AsyncDisplayKit/ASDisplayNode.mm @@ -1700,7 +1700,7 @@ static void _recursivelySetDisplaySuspended(ASDisplayNode *node, CALayer *layer, static dispatch_queue_t asyncSizingQueue = NULL; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ - asyncSizingQueue = dispatch_queue_create("com.facebook.AsyncDisplayKit.ASDisplayNode.asyncSizingQueue", DISPATCH_QUEUE_CONCURRENT); + asyncSizingQueue = dispatch_queue_create("org.AsyncDisplayKit.ASDisplayNode.asyncSizingQueue", DISPATCH_QUEUE_CONCURRENT); // we use the highpri queue to prioritize UI rendering over other async operations dispatch_set_target_queue(asyncSizingQueue, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)); }); diff --git a/AsyncDisplayKit/ASTableView.mm b/AsyncDisplayKit/ASTableView.mm index 080fe4f570..2085b6f543 100644 --- a/AsyncDisplayKit/ASTableView.mm +++ b/AsyncDisplayKit/ASTableView.mm @@ -125,7 +125,7 @@ static BOOL _isInterceptedSelector(SEL sel) ASBatchContext *_batchContext; - NSMutableSet *_pendingVisibleIndexPaths; + NSIndexPath *_pendingVisibleIndexPath; } @property (atomic, assign) BOOL asyncDataSourceLocked; @@ -174,8 +174,6 @@ void ASPerformBlockWithoutAnimation(BOOL withoutAnimation, void (^block)()) { _leadingScreensForBatching = 1.0; _batchContext = [[ASBatchContext alloc] init]; - - _pendingVisibleIndexPaths = [[NSMutableSet alloc] init]; } - (instancetype)initWithFrame:(CGRect)frame style:(UITableViewStyle)style @@ -273,7 +271,7 @@ void ASPerformBlockWithoutAnimation(BOOL withoutAnimation, void (^block)()) { ASDisplayNodePerformBlockOnMainThread(^{ [super reloadData]; }); - [_dataController reloadDataWithAnimationOption:UITableViewRowAnimationNone completion:completion]; + [_dataController reloadDataWithAnimationOptions:UITableViewRowAnimationNone completion:completion]; } - (void)reloadData @@ -335,42 +333,42 @@ void ASPerformBlockWithoutAnimation(BOOL withoutAnimation, void (^block)()) { - (void)insertSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation { - [_dataController insertSections:sections withAnimationOption:animation]; + [_dataController insertSections:sections withAnimationOptions:animation]; } - (void)deleteSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation { - [_dataController deleteSections:sections withAnimationOption:animation]; + [_dataController deleteSections:sections withAnimationOptions:animation]; } - (void)reloadSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation { - [_dataController reloadSections:sections withAnimationOption:animation]; + [_dataController reloadSections:sections withAnimationOptions:animation]; } - (void)moveSection:(NSInteger)section toSection:(NSInteger)newSection { - [_dataController moveSection:section toSection:newSection withAnimationOption:UITableViewRowAnimationNone]; + [_dataController moveSection:section toSection:newSection withAnimationOptions:UITableViewRowAnimationNone]; } - (void)insertRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation { - [_dataController insertRowsAtIndexPaths:indexPaths withAnimationOption:animation]; + [_dataController insertRowsAtIndexPaths:indexPaths withAnimationOptions:animation]; } - (void)deleteRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation { - [_dataController deleteRowsAtIndexPaths:indexPaths withAnimationOption:animation]; + [_dataController deleteRowsAtIndexPaths:indexPaths withAnimationOptions:animation]; } - (void)reloadRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation { - [_dataController reloadRowsAtIndexPaths:indexPaths withAnimationOption:animation]; + [_dataController reloadRowsAtIndexPaths:indexPaths withAnimationOptions:animation]; } - (void)moveRowAtIndexPath:(NSIndexPath *)indexPath toIndexPath:(NSIndexPath *)newIndexPath { - [_dataController moveRowAtIndexPath:indexPath toIndexPath:newIndexPath withAnimationOption:UITableViewRowAnimationNone]; + [_dataController moveRowAtIndexPath:indexPath toIndexPath:newIndexPath withAnimationOptions:UITableViewRowAnimationNone]; } #pragma mark - @@ -433,7 +431,7 @@ void ASPerformBlockWithoutAnimation(BOOL withoutAnimation, void (^block)()) { - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath { - [_pendingVisibleIndexPaths addObject:indexPath]; + _pendingVisibleIndexPath = indexPath; [_rangeController visibleNodeIndexPathsDidChangeWithScrollDirection:self.scrollDirection]; @@ -444,8 +442,8 @@ void ASPerformBlockWithoutAnimation(BOOL withoutAnimation, void (^block)()) { - (void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath*)indexPath { - if ([_pendingVisibleIndexPaths containsObject:indexPath]) { - [_pendingVisibleIndexPaths removeObject:indexPath]; + if ([_pendingVisibleIndexPath isEqual:indexPath]) { + _pendingVisibleIndexPath = nil; } [_rangeController visibleNodeIndexPathsDidChangeWithScrollDirection:self.scrollDirection]; @@ -519,15 +517,50 @@ void ASPerformBlockWithoutAnimation(BOOL withoutAnimation, void (^block)()) { { ASDisplayNodeAssertMainThread(); - NSMutableSet *visibleIndexPaths = [NSMutableSet setWithArray:[self indexPathsForVisibleRows]]; - - // First, remove any index paths we're tracking that UIKit has now proven it can remember :) - [_pendingVisibleIndexPaths minusSet:visibleIndexPaths]; - - // Next, add all remaining index paths that we know should be visible (from willDisplayCell) but are not in the set. - [visibleIndexPaths unionSet:_pendingVisibleIndexPaths]; - - return visibleIndexPaths.allObjects; + NSArray *visibleIndexPaths = self.indexPathsForVisibleRows; + + if ( _pendingVisibleIndexPath ) { + NSMutableSet *indexPaths = [NSMutableSet setWithArray:self.indexPathsForVisibleRows]; + + BOOL (^isAfter)(NSIndexPath *, NSIndexPath *) = ^BOOL(NSIndexPath *indexPath, NSIndexPath *anchor) { + if (!anchor || !indexPath) { + return NO; + } + if (indexPath.section == anchor.section) { + return (indexPath.row == anchor.row+1); // assumes that indexes are valid + + } else if (indexPath.section > anchor.section && indexPath.row == 0) { + if (anchor.row != [_dataController numberOfRowsInSection:anchor.section] -1) { + return NO; // anchor is not at the end of the section + } + + NSInteger nextSection = anchor.section+1; + while([_dataController numberOfRowsInSection:nextSection] == 0) { + ++nextSection; + } + + return indexPath.section == nextSection; + } + + return NO; + }; + + BOOL (^isBefore)(NSIndexPath *, NSIndexPath *) = ^BOOL(NSIndexPath *indexPath, NSIndexPath *anchor) { + return isAfter(anchor, indexPath); + }; + + if ( [indexPaths containsObject:_pendingVisibleIndexPath]) { + _pendingVisibleIndexPath = nil; // once it has shown up in visibleIndexPaths, we can stop tracking it + } else if (!isBefore(_pendingVisibleIndexPath, visibleIndexPaths.firstObject) && + !isAfter(_pendingVisibleIndexPath, visibleIndexPaths.lastObject)) { + _pendingVisibleIndexPath = nil; // not contiguous, ignore. + } else { + [indexPaths addObject:_pendingVisibleIndexPath]; + visibleIndexPaths = [indexPaths.allObjects sortedArrayUsingSelector:@selector(compare:)]; + } + } + + return visibleIndexPaths; } - (NSArray *)rangeController:(ASRangeController *)rangeController nodesAtIndexPaths:(NSArray *)indexPaths @@ -541,43 +574,43 @@ void ASPerformBlockWithoutAnimation(BOOL withoutAnimation, void (^block)()) { return self.bounds.size; } -- (void)rangeController:(ASRangeController *)rangeController didInsertNodesAtIndexPaths:(NSArray *)indexPaths withAnimationOption:(ASDataControllerAnimationOptions)animationOption +- (void)rangeController:(ASRangeController *)rangeController didInsertNodesAtIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions { ASDisplayNodeAssertMainThread(); - - BOOL preventAnimation = animationOption == UITableViewRowAnimationNone; + + BOOL preventAnimation = animationOptions == UITableViewRowAnimationNone; ASPerformBlockWithoutAnimation(preventAnimation, ^{ - [super insertRowsAtIndexPaths:indexPaths withRowAnimation:(UITableViewRowAnimation)animationOption]; + [super insertRowsAtIndexPaths:indexPaths withRowAnimation:(UITableViewRowAnimation)animationOptions]; }); } -- (void)rangeController:(ASRangeController *)rangeController didDeleteNodesAtIndexPaths:(NSArray *)indexPaths withAnimationOption:(ASDataControllerAnimationOptions)animationOption +- (void)rangeController:(ASRangeController *)rangeController didDeleteNodesAtIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions { ASDisplayNodeAssertMainThread(); - BOOL preventAnimation = animationOption == UITableViewRowAnimationNone; + BOOL preventAnimation = animationOptions == UITableViewRowAnimationNone; ASPerformBlockWithoutAnimation(preventAnimation, ^{ - [super deleteRowsAtIndexPaths:indexPaths withRowAnimation:(UITableViewRowAnimation)animationOption]; + [super deleteRowsAtIndexPaths:indexPaths withRowAnimation:(UITableViewRowAnimation)animationOptions]; }); } -- (void)rangeController:(ASRangeController *)rangeController didInsertSectionsAtIndexSet:(NSIndexSet *)indexSet withAnimationOption:(ASDataControllerAnimationOptions)animationOption +- (void)rangeController:(ASRangeController *)rangeController didInsertSectionsAtIndexSet:(NSIndexSet *)indexSet withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions { ASDisplayNodeAssertMainThread(); - BOOL preventAnimation = animationOption == UITableViewRowAnimationNone; + BOOL preventAnimation = animationOptions == UITableViewRowAnimationNone; ASPerformBlockWithoutAnimation(preventAnimation, ^{ - [super insertSections:indexSet withRowAnimation:(UITableViewRowAnimation)animationOption]; + [super insertSections:indexSet withRowAnimation:(UITableViewRowAnimation)animationOptions]; }); } -- (void)rangeController:(ASRangeController *)rangeController didDeleteSectionsAtIndexSet:(NSIndexSet *)indexSet withAnimationOption:(ASDataControllerAnimationOptions)animationOption +- (void)rangeController:(ASRangeController *)rangeController didDeleteSectionsAtIndexSet:(NSIndexSet *)indexSet withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions { ASDisplayNodeAssertMainThread(); - BOOL preventAnimation = animationOption == UITableViewRowAnimationNone; + BOOL preventAnimation = animationOptions == UITableViewRowAnimationNone; ASPerformBlockWithoutAnimation(preventAnimation, ^{ - [super deleteSections:indexSet withRowAnimation:(UITableViewRowAnimation)animationOption]; + [super deleteSections:indexSet withRowAnimation:(UITableViewRowAnimation)animationOptions]; }); } diff --git a/AsyncDisplayKit/Details/ASDataController.h b/AsyncDisplayKit/Details/ASDataController.h index 8926b47598..a9aa7e55ac 100644 --- a/AsyncDisplayKit/Details/ASDataController.h +++ b/AsyncDisplayKit/Details/ASDataController.h @@ -70,26 +70,26 @@ typedef NSUInteger ASDataControllerAnimationOptions; /** Called for insertion of elements. */ -- (void)dataController:(ASDataController *)dataController willInsertNodes:(NSArray *)nodes atIndexPaths:(NSArray *)indexPaths withAnimationOption:(ASDataControllerAnimationOptions)animationOption; -- (void)dataController:(ASDataController *)dataController didInsertNodes:(NSArray *)nodes atIndexPaths:(NSArray *)indexPaths withAnimationOption:(ASDataControllerAnimationOptions)animationOption; +- (void)dataController:(ASDataController *)dataController willInsertNodes:(NSArray *)nodes atIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions; +- (void)dataController:(ASDataController *)dataController didInsertNodes:(NSArray *)nodes atIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions; /** Called for deletion of elements. */ -- (void)dataController:(ASDataController *)dataController willDeleteNodesAtIndexPaths:(NSArray *)indexPaths withAnimationOption:(ASDataControllerAnimationOptions)animationOption; -- (void)dataController:(ASDataController *)dataController didDeleteNodesAtIndexPaths:(NSArray *)indexPaths withAnimationOption:(ASDataControllerAnimationOptions)animationOption; +- (void)dataController:(ASDataController *)dataController willDeleteNodesAtIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions; +- (void)dataController:(ASDataController *)dataController didDeleteNodesAtIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions; /** Called for insertion of sections. */ -- (void)dataController:(ASDataController *)dataController willInsertSections:(NSArray *)sections atIndexSet:(NSIndexSet *)indexSet withAnimationOption:(ASDataControllerAnimationOptions)animationOption; -- (void)dataController:(ASDataController *)dataController didInsertSections:(NSArray *)sections atIndexSet:(NSIndexSet *)indexSet withAnimationOption:(ASDataControllerAnimationOptions)animationOption; +- (void)dataController:(ASDataController *)dataController willInsertSections:(NSArray *)sections atIndexSet:(NSIndexSet *)indexSet withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions; +- (void)dataController:(ASDataController *)dataController didInsertSections:(NSArray *)sections atIndexSet:(NSIndexSet *)indexSet withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions; /** Called for deletion of sections. */ -- (void)dataController:(ASDataController *)dataController willDeleteSectionsAtIndexSet:(NSIndexSet *)indexSet withAnimationOption:(ASDataControllerAnimationOptions)animationOption; -- (void)dataController:(ASDataController *)dataController didDeleteSectionsAtIndexSet:(NSIndexSet *)indexSet withAnimationOption:(ASDataControllerAnimationOptions)animationOption; +- (void)dataController:(ASDataController *)dataController willDeleteSectionsAtIndexSet:(NSIndexSet *)indexSet withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions; +- (void)dataController:(ASDataController *)dataController didDeleteSectionsAtIndexSet:(NSIndexSet *)indexSet withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions; @end @@ -129,7 +129,7 @@ typedef NSUInteger ASDataControllerAnimationOptions; /** @name Initial loading */ -- (void)initialDataLoadingWithAnimationOption:(ASDataControllerAnimationOptions)animationOption; +- (void)initialDataLoadingWithAnimationOptions:(ASDataControllerAnimationOptions)animationOptions; /** @name Data Updating */ @@ -139,23 +139,23 @@ typedef NSUInteger ASDataControllerAnimationOptions; - (void)endUpdatesWithCompletion:(void (^)(BOOL))completion; -- (void)insertSections:(NSIndexSet *)sections withAnimationOption:(ASDataControllerAnimationOptions)animationOption; +- (void)insertSections:(NSIndexSet *)sections withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions; -- (void)deleteSections:(NSIndexSet *)sections withAnimationOption:(ASDataControllerAnimationOptions)animationOption;; +- (void)deleteSections:(NSIndexSet *)sections withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions; -- (void)reloadSections:(NSIndexSet *)sections withAnimationOption:(ASDataControllerAnimationOptions)animationOption; +- (void)reloadSections:(NSIndexSet *)sections withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions; -- (void)moveSection:(NSInteger)section toSection:(NSInteger)newSection withAnimationOption:(ASDataControllerAnimationOptions)animationOption;; +- (void)moveSection:(NSInteger)section toSection:(NSInteger)newSection withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions; -- (void)insertRowsAtIndexPaths:(NSArray *)indexPaths withAnimationOption:(ASDataControllerAnimationOptions)animationOption; +- (void)insertRowsAtIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions; -- (void)deleteRowsAtIndexPaths:(NSArray *)indexPaths withAnimationOption:(ASDataControllerAnimationOptions)animationOption; +- (void)deleteRowsAtIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions; -- (void)reloadRowsAtIndexPaths:(NSArray *)indexPaths withAnimationOption:(ASDataControllerAnimationOptions)animationOption; +- (void)reloadRowsAtIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions; -- (void)moveRowAtIndexPath:(NSIndexPath *)indexPath toIndexPath:(NSIndexPath *)newIndexPath withAnimationOption:(ASDataControllerAnimationOptions)animationOption;; +- (void)moveRowAtIndexPath:(NSIndexPath *)indexPath toIndexPath:(NSIndexPath *)newIndexPath withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions; -- (void)reloadDataWithAnimationOption:(ASDataControllerAnimationOptions)animationOption completion:(void (^)())completion; +- (void)reloadDataWithAnimationOptions:(ASDataControllerAnimationOptions)animationOptions completion:(void (^)())completion; /** @name Data Querying */ diff --git a/AsyncDisplayKit/Details/ASDataController.mm b/AsyncDisplayKit/Details/ASDataController.mm index 5a1e561911..bfb56d3b67 100644 --- a/AsyncDisplayKit/Details/ASDataController.mm +++ b/AsyncDisplayKit/Details/ASDataController.mm @@ -16,50 +16,6 @@ #import "ASMultidimensionalArrayUtils.h" #import "ASDisplayNodeInternal.h" -#define INSERT_NODES(multidimensionalArray, indexPath, elements, animationOption) \ -{ \ - if ([_delegate respondsToSelector:@selector(dataController:willInsertNodes:atIndexPaths:withAnimationOption:)]) { \ - [_delegate dataController:self willInsertNodes:elements atIndexPaths:indexPath withAnimationOption:animationOption]; \ - } \ - ASInsertElementsIntoMultidimensionalArrayAtIndexPaths(multidimensionalArray, indexPath, elements); \ - if ([_delegate respondsToSelector:@selector(dataController:didInsertNodes:atIndexPaths:withAnimationOption:)]) { \ - [_delegate dataController:self didInsertNodes:elements atIndexPaths:indexPath withAnimationOption:animationOption]; \ - } \ -} - -#define DELETE_NODES(multidimensionalArray, indexPath, animationOption) \ -{ \ - if ([_delegate respondsToSelector:@selector(dataController:willDeleteNodesAtIndexPaths:withAnimationOption:)]) { \ - [_delegate dataController:self willDeleteNodesAtIndexPaths:indexPath withAnimationOption:animationOption]; \ - } \ - ASDeleteElementsInMultidimensionalArrayAtIndexPaths(multidimensionalArray, indexPath); \ - if ([_delegate respondsToSelector:@selector(dataController:didDeleteNodesAtIndexPaths:withAnimationOption:)]) { \ - [_delegate dataController:self didDeleteNodesAtIndexPaths:indexPath withAnimationOption:animationOption]; \ - } \ -} - -#define INSERT_SECTIONS(multidimensionalArray, indexSet, sections, animationOption) \ -{ \ - if ([_delegate respondsToSelector:@selector(dataController:willInsertSections:atIndexSet:withAnimationOption:)]) { \ - [_delegate dataController:self willInsertSections:sections atIndexSet:indexSet withAnimationOption:animationOption]; \ - } \ - [multidimensionalArray insertObjects:sections atIndexes:indexSet]; \ - if ([_delegate respondsToSelector:@selector(dataController:didInsertSections:atIndexSet:withAnimationOption:)]) { \ - [_delegate dataController:self didInsertSections:sections atIndexSet:indexSet withAnimationOption:animationOption]; \ - } \ -} - -#define DELETE_SECTIONS(multidimensionalArray, indexSet, animationOption) \ -{ \ - if ([_delegate respondsToSelector:@selector(dataController:willDeleteSectionsAtIndexSet:withAnimationOption:)]) { \ - [_delegate dataController:self willDeleteSectionsAtIndexSet:indexSet withAnimationOption:animationOption]; \ - } \ - [multidimensionalArray removeObjectsAtIndexes:indexSet]; \ - if ([_delegate respondsToSelector:@selector(dataController:didDeleteSectionsAtIndexSet:withAnimationOption:)]) { \ - [_delegate dataController:self didDeleteSectionsAtIndexSet:indexSet withAnimationOption:animationOption]; \ - } \ -} - const static NSUInteger kASDataControllerSizingCountPerProcessor = 5; static void *kASSizingQueueContext = &kASSizingQueueContext; @@ -68,6 +24,14 @@ static void *kASSizingQueueContext = &kASSizingQueueContext; NSMutableArray *_nodes; NSMutableArray *_pendingBlocks; BOOL _asyncDataFetchingEnabled; + BOOL _delegateWillInsertNodes; + BOOL _delegateDidInsertNodes; + BOOL _delegateWillDeleteNodes; + BOOL _delegateDidDeleteNodes; + BOOL _delegateWillInsertSections; + BOOL _delegateDidInsertSections; + BOOL _delegateWillDeleteSections; + BOOL _delegateDidDeleteSections; } @property (atomic, assign) NSUInteger batchUpdateCounter; @@ -76,20 +40,45 @@ static void *kASSizingQueueContext = &kASSizingQueueContext; @implementation ASDataController -- (instancetype)initWithAsyncDataFetching:(BOOL)asyncDataFetchingEnabled { - if (self = [super init]) { - _nodes = [NSMutableArray array]; - _pendingBlocks = [NSMutableArray array]; - _batchUpdateCounter = 0; - _asyncDataFetchingEnabled = asyncDataFetchingEnabled; - } +#pragma mark - Lifecycle +- (instancetype)initWithAsyncDataFetching:(BOOL)asyncDataFetchingEnabled +{ + if (!(self = [super init])) { + return nil; + } + + _nodes = [NSMutableArray array]; + _pendingBlocks = [NSMutableArray array]; + _batchUpdateCounter = 0; + _asyncDataFetchingEnabled = asyncDataFetchingEnabled; + return self; } -#pragma mark - Utils +- (void)setDelegate:(id)delegate +{ + if (_delegate == delegate) { + return; + } + + _delegate = delegate; + + // Interrogate our delegate to understand its capabilities, optimizing away expensive respondsToSelector: calls later. + _delegateWillInsertNodes = [_delegate respondsToSelector:@selector(dataController:willInsertNodes:atIndexPaths:withAnimationOptions:)]; + _delegateDidInsertNodes = [_delegate respondsToSelector:@selector(dataController:didInsertNodes:atIndexPaths:withAnimationOptions:)]; + _delegateWillDeleteNodes = [_delegate respondsToSelector:@selector(dataController:willDeleteNodesAtIndexPaths:withAnimationOptions:)]; + _delegateDidDeleteNodes = [_delegate respondsToSelector:@selector(dataController:didDeleteNodesAtIndexPaths:withAnimationOptions:)]; + _delegateWillInsertSections = [_delegate respondsToSelector:@selector(dataController:willInsertSections:atIndexSet:withAnimationOptions:)]; + _delegateDidInsertSections = [_delegate respondsToSelector:@selector(dataController:didInsertSections:atIndexSet:withAnimationOptions:)]; + _delegateWillDeleteSections = [_delegate respondsToSelector:@selector(dataController:willDeleteSectionsAtIndexSet:withAnimationOptions:)]; + _delegateDidDeleteSections = [_delegate respondsToSelector:@selector(dataController:didDeleteSectionsAtIndexSet:withAnimationOptions:)]; +} -+ (NSUInteger)parallelProcessorCount { +#pragma mark - Queue Management + ++ (NSUInteger)parallelProcessorCount +{ static NSUInteger parallelProcessorCount; static dispatch_once_t onceToken; @@ -105,7 +94,7 @@ static void *kASSizingQueueContext = &kASSizingQueueContext; static dispatch_queue_t sizingQueue = NULL; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ - sizingQueue = dispatch_queue_create("com.facebook.AsyncDisplayKit.ASDataController.sizingQueue", DISPATCH_QUEUE_SERIAL); + sizingQueue = dispatch_queue_create("org.AsyncDisplayKit.ASDataController.sizingQueue", DISPATCH_QUEUE_SERIAL); dispatch_queue_set_specific(sizingQueue, kASSizingQueueContext, kASSizingQueueContext, NULL); dispatch_set_target_queue(sizingQueue, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)); }); @@ -138,7 +127,7 @@ static void *kASSizingQueueContext = &kASSizingQueueContext; }); } -- (void)performDataFetchingWithBlock:(dispatch_block_t)block { +- (void)accessDataSourceWithBlock:(dispatch_block_t)block { if (_asyncDataFetchingEnabled) { [_dataSource dataControllerLockDataSource]; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ @@ -152,15 +141,124 @@ static void *kASSizingQueueContext = &kASSizingQueueContext; } } -#pragma mark - Initial Data Loading +#pragma mark - Cell Layout -- (void)initialDataLoadingWithAnimationOption:(ASDataControllerAnimationOptions)animationOption { - [self performDataFetchingWithBlock:^{ +- (void)_layoutNodes:(NSArray *)nodes + atIndexPaths:(NSArray *)indexPaths +withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions +{ + if (!nodes.count) { + return; + } + + dispatch_group_t layoutGroup = dispatch_group_create(); + + for (NSUInteger j = 0; j < nodes.count && j < indexPaths.count; j += kASDataControllerSizingCountPerProcessor) { + NSArray *subIndexPaths = [indexPaths subarrayWithRange:NSMakeRange(j, MIN(kASDataControllerSizingCountPerProcessor, indexPaths.count - j))]; + + // TODO: The current implementation does not make use of different constrained sizes per node. + // There should be a fast-path that avoids all of this object creation. + NSMutableArray *nodeBoundSizes = [[NSMutableArray alloc] initWithCapacity:kASDataControllerSizingCountPerProcessor]; + [subIndexPaths enumerateObjectsUsingBlock:^(NSIndexPath *indexPath, NSUInteger idx, BOOL *stop) { + [nodeBoundSizes addObject:[NSValue valueWithCGSize:[_dataSource dataController:self constrainedSizeForNodeAtIndexPath:indexPath]]]; + }]; + + dispatch_group_async(layoutGroup, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + [subIndexPaths enumerateObjectsUsingBlock:^(NSIndexPath *indexPath, NSUInteger idx, BOOL *stop) { + ASCellNode *node = nodes[j + idx]; + [node measure:[nodeBoundSizes[idx] CGSizeValue]]; + node.frame = CGRectMake(0.0f, 0.0f, node.calculatedSize.width, node.calculatedSize.height); + }]; + }); + } + + dispatch_block_t block = ^{ + dispatch_group_wait(layoutGroup, DISPATCH_TIME_FOREVER); + + [self asyncUpdateDataWithBlock:^{ + // Insert finished nodes into data storage + [self _insertNodes:nodes atIndexPaths:indexPaths withAnimationOptions:animationOptions]; + }]; + }; + + if ([ASDataController executingOnSizingQueue]) { + block(); + } else { + dispatch_async([ASDataController sizingQueue], block); + } +} + +- (void)_batchLayoutNodes:(NSArray *)nodes + atIndexPaths:(NSArray *)indexPaths + withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions +{ + NSUInteger blockSize = [[ASDataController class] parallelProcessorCount] * kASDataControllerSizingCountPerProcessor; + + // Processing in batches + for (NSUInteger i = 0; i < indexPaths.count; i += blockSize) { + NSRange batchedRange = NSMakeRange(i, MIN(indexPaths.count - i, blockSize)); + NSArray *batchedIndexPaths = [indexPaths subarrayWithRange:batchedRange]; + NSArray *batchedNodes = [nodes subarrayWithRange:batchedRange]; + + [self _layoutNodes:batchedNodes atIndexPaths:batchedIndexPaths withAnimationOptions:animationOptions]; + } +} + +#pragma mark - Internal Data Editing + +- (void)_insertNodes:(NSArray *)nodes atIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions +{ + if (indexPaths.count == 0) + return; + if (_delegateWillInsertNodes) + [_delegate dataController:self willInsertNodes:nodes atIndexPaths:indexPaths withAnimationOptions:animationOptions]; + ASInsertElementsIntoMultidimensionalArrayAtIndexPaths(_nodes, indexPaths, nodes); + if (_delegateDidInsertNodes) + [_delegate dataController:self didInsertNodes:nodes atIndexPaths:indexPaths withAnimationOptions:animationOptions]; +} + +- (void)_deleteNodesAtIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions +{ + if (indexPaths.count == 0) + return; + if (_delegateWillDeleteNodes) + [_delegate dataController:self willDeleteNodesAtIndexPaths:indexPaths withAnimationOptions:animationOptions]; + ASDeleteElementsInMultidimensionalArrayAtIndexPaths(_nodes, indexPaths); + if (_delegateDidDeleteNodes) + [_delegate dataController:self didDeleteNodesAtIndexPaths:indexPaths withAnimationOptions:animationOptions]; +} + +- (void)_insertSections:(NSArray *)sections atIndexSet:(NSIndexSet *)indexSet withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions +{ + if (indexSet.count == 0) + return; + if (_delegateWillInsertSections) + [_delegate dataController:self willInsertSections:sections atIndexSet:indexSet withAnimationOptions:animationOptions]; + [_nodes insertObjects:sections atIndexes:indexSet]; + if (_delegateDidInsertSections) + [_delegate dataController:self didInsertSections:sections atIndexSet:indexSet withAnimationOptions:animationOptions]; +} + +- (void)_deleteSectionsAtIndexSet:(NSIndexSet *)indexSet withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions +{ + if (indexSet.count == 0) + return; + if (_delegateWillDeleteSections) + [_delegate dataController:self willDeleteSectionsAtIndexSet:indexSet withAnimationOptions:animationOptions]; + [_nodes removeObjectsAtIndexes:indexSet]; + if (_delegateDidDeleteSections) + [_delegate dataController:self didDeleteSectionsAtIndexSet:indexSet withAnimationOptions:animationOptions]; +} + +#pragma mark - Initial Load & Full Reload (External API) + +- (void)initialDataLoadingWithAnimationOptions:(ASDataControllerAnimationOptions)animationOptions { + [self accessDataSourceWithBlock:^{ NSMutableArray *indexPaths = [NSMutableArray array]; NSUInteger sectionNum = [_dataSource dataControllerNumberOfSections:self]; // insert sections - [self insertSections:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, sectionNum)] withAnimationOption:0]; + [self insertSections:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, sectionNum)] withAnimationOptions:0]; for (NSUInteger i = 0; i < sectionNum; i++) { NSIndexPath *indexPath = [[NSIndexPath alloc] initWithIndex:i]; @@ -172,12 +270,58 @@ static void *kASSizingQueueContext = &kASSizingQueueContext; } // insert elements - [self insertRowsAtIndexPaths:indexPaths withAnimationOption:animationOption]; + [self insertRowsAtIndexPaths:indexPaths withAnimationOptions:animationOptions]; }]; } -#pragma mark - Data Update +- (void)reloadDataWithAnimationOptions:(ASDataControllerAnimationOptions)animationOptions completion:(void (^)())completion +{ + [self accessDataSourceWithBlock:^{ + // Fetching data in calling thread + NSMutableArray *updatedNodes = [[NSMutableArray alloc] init]; + NSMutableArray *updatedIndexPaths = [[NSMutableArray alloc] init]; + + NSUInteger sectionNum = [_dataSource dataControllerNumberOfSections: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]; + [updatedIndexPaths addObject:indexPath]; + [updatedNodes addObject:[_dataSource dataController:self nodeAtIndexPath:indexPath]]; + } + } + + dispatch_async([ASDataController sizingQueue], ^{ + [self syncUpdateDataWithBlock:^{ + // Remove everything that existed before the reload, now that we're ready to insert replacements + NSArray *indexPaths = ASIndexPathsForMultidimensionalArray(_nodes); + [self _deleteNodesAtIndexPaths:indexPaths withAnimationOptions:animationOptions]; + + NSMutableIndexSet *indexSet = [[NSMutableIndexSet alloc] initWithIndexesInRange:NSMakeRange(0, _nodes.count)]; + [self deleteSections:indexSet withAnimationOptions:animationOptions]; + + // Insert each section + NSMutableArray *sections = [[NSMutableArray alloc] initWithCapacity:sectionNum]; + for (int i = 0; i < sectionNum; i++) { + [sections addObject:[[NSMutableArray alloc] init]]; + } + + [self _insertSections:sections atIndexSet:[[NSIndexSet alloc] initWithIndexesInRange:NSMakeRange(0, sectionNum)] withAnimationOptions:animationOptions]; + }]; + + [self _batchLayoutNodes:updatedNodes atIndexPaths:updatedIndexPaths withAnimationOptions:animationOptions]; + + if (completion) { + dispatch_async(dispatch_get_main_queue(), completion); + } + }); + }]; +} + +#pragma mark - Batching (External API) - (void)beginUpdates { @@ -188,7 +332,8 @@ static void *kASSizingQueueContext = &kASSizingQueueContext; }); } -- (void)endUpdates { +- (void)endUpdates +{ [self endUpdatesWithCompletion:NULL]; } @@ -210,9 +355,11 @@ static void *kASSizingQueueContext = &kASSizingQueueContext; }); } -- (void)insertSections:(NSIndexSet *)indexSet withAnimationOption:(ASDataControllerAnimationOptions)animationOption +#pragma mark - Section Editing (External API) + +- (void)insertSections:(NSIndexSet *)indexSet withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions { - [self performDataFetchingWithBlock:^{ + [self accessDataSourceWithBlock:^{ __block int nodeTotalCnt = 0; NSMutableArray *nodeCounts = [NSMutableArray arrayWithCapacity:indexSet.count]; [indexSet enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) { @@ -243,30 +390,30 @@ static void *kASSizingQueueContext = &kASSizingQueueContext; for (NSUInteger i = 0; i < indexSet.count; i++) { [sectionArray addObject:[NSMutableArray array]]; } - INSERT_SECTIONS(_nodes , indexSet, sectionArray, animationOption); + [self _insertSections:sectionArray atIndexSet:indexSet withAnimationOptions:animationOptions]; }]; - [self _batchInsertNodes:nodes atIndexPaths:indexPaths withAnimationOptions:animationOption]; + [self _batchLayoutNodes:nodes atIndexPaths:indexPaths withAnimationOptions:animationOptions]; }); }]; } -- (void)deleteSections:(NSIndexSet *)indexSet withAnimationOption:(ASDataControllerAnimationOptions)animationOption +- (void)deleteSections:(NSIndexSet *)indexSet withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions { dispatch_async([[self class] sizingQueue], ^{ [self asyncUpdateDataWithBlock:^{ // remove elements NSArray *indexPaths = ASIndexPathsForMultidimensionalArrayAtIndexSet(_nodes, indexSet); - DELETE_NODES(_nodes, indexPaths, animationOption); - DELETE_SECTIONS(_nodes, indexSet, animationOption); + [self _deleteNodesAtIndexPaths:indexPaths withAnimationOptions:animationOptions]; + [self _deleteSectionsAtIndexSet:indexSet withAnimationOptions:animationOptions]; }]; }); } -- (void)reloadSections:(NSIndexSet *)sections withAnimationOption:(ASDataControllerAnimationOptions)animationOption +- (void)reloadSections:(NSIndexSet *)sections withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions { - [self performDataFetchingWithBlock:^{ + [self accessDataSourceWithBlock:^{ // We need to keep data query on data source in the calling thread. NSMutableArray *updatedIndexPaths = [[NSMutableArray alloc] init]; NSMutableArray *updatedNodes = [[NSMutableArray alloc] init]; @@ -289,23 +436,23 @@ static void *kASSizingQueueContext = &kASSizingQueueContext; [self syncUpdateDataWithBlock:^{ // remove elements NSArray *indexPaths = ASIndexPathsForMultidimensionalArrayAtIndexSet(_nodes, sections); - DELETE_NODES(_nodes, indexPaths, animationOption); + [self _deleteNodesAtIndexPaths:indexPaths withAnimationOptions:animationOptions]; }]; // reinsert the elements - [self _batchInsertNodes:updatedNodes atIndexPaths:updatedIndexPaths withAnimationOptions:animationOption]; + [self _batchLayoutNodes:updatedNodes atIndexPaths:updatedIndexPaths withAnimationOptions:animationOptions]; }); }]; } -- (void)moveSection:(NSInteger)section toSection:(NSInteger)newSection withAnimationOption:(ASDataControllerAnimationOptions)animationOption +- (void)moveSection:(NSInteger)section toSection:(NSInteger)newSection withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions { dispatch_async([ASDataController sizingQueue], ^{ [self asyncUpdateDataWithBlock:^{ // remove elements NSArray *indexPaths = ASIndexPathsForMultidimensionalArrayAtIndexSet(_nodes, [NSIndexSet indexSetWithIndex:section]); NSArray *nodes = ASFindElementsInMultidimensionalArrayAtIndexPaths(_nodes, indexPaths); - DELETE_NODES(_nodes, indexPaths, animationOption); + [self _deleteNodesAtIndexPaths:indexPaths withAnimationOptions:animationOptions]; // update the section of indexpaths NSIndexPath *sectionIndexPath = [[NSIndexPath alloc] initWithIndex:newSection]; @@ -315,75 +462,16 @@ static void *kASSizingQueueContext = &kASSizingQueueContext; }]; // Don't re-calculate size for moving - INSERT_NODES(_nodes, updatedIndexPaths, nodes, animationOption); + [self _insertNodes:nodes atIndexPaths:updatedIndexPaths withAnimationOptions:animationOptions]; }]; }); } -- (void)_insertNodes:(NSArray *)nodes - atIndexPaths:(NSArray *)indexPaths - withAnimationOption:(ASDataControllerAnimationOptions)animationOption +#pragma mark - Row Editing (External API) + +- (void)insertRowsAtIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions { - if (!nodes.count) { - return; - } - - dispatch_group_t layoutGroup = dispatch_group_create(); - - for (NSUInteger j = 0; j < nodes.count && j < indexPaths.count; j += kASDataControllerSizingCountPerProcessor) { - NSArray *subIndexPaths = [indexPaths subarrayWithRange:NSMakeRange(j, MIN(kASDataControllerSizingCountPerProcessor, indexPaths.count - j))]; - - // TODO: The current implementation does not make use of different constrained sizes per node. - // There should be a fast-path that avoids all of this object creation. - NSMutableArray *nodeBoundSizes = [[NSMutableArray alloc] initWithCapacity:kASDataControllerSizingCountPerProcessor]; - [subIndexPaths enumerateObjectsUsingBlock:^(NSIndexPath *indexPath, NSUInteger idx, BOOL *stop) { - [nodeBoundSizes addObject:[NSValue valueWithCGSize:[_dataSource dataController:self constrainedSizeForNodeAtIndexPath:indexPath]]]; - }]; - - dispatch_group_async(layoutGroup, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - [subIndexPaths enumerateObjectsUsingBlock:^(NSIndexPath *indexPath, NSUInteger idx, BOOL *stop) { - ASCellNode *node = nodes[j + idx]; - [node measure:[nodeBoundSizes[idx] CGSizeValue]]; - node.frame = CGRectMake(0.0f, 0.0f, node.calculatedSize.width, node.calculatedSize.height); - }]; - }); - } - - dispatch_block_t block = ^{ - dispatch_group_wait(layoutGroup, DISPATCH_TIME_FOREVER); - - [self asyncUpdateDataWithBlock:^{ - // Insert finished nodes into data storage - INSERT_NODES(_nodes, indexPaths, nodes, animationOption); - }]; - }; - - if ([ASDataController executingOnSizingQueue]) { - block(); - } else { - dispatch_async([ASDataController sizingQueue], block); - } -} - -- (void)_batchInsertNodes:(NSArray *)nodes - atIndexPaths:(NSArray *)indexPaths - withAnimationOptions:(ASDataControllerAnimationOptions)animationOption -{ - NSUInteger blockSize = [[ASDataController class] parallelProcessorCount] * kASDataControllerSizingCountPerProcessor; - - // Processing in batches - for (NSUInteger i = 0; i < indexPaths.count; i += blockSize) { - NSRange batchedRange = NSMakeRange(i, MIN(indexPaths.count - i, blockSize)); - NSArray *batchedIndexPaths = [indexPaths subarrayWithRange:batchedRange]; - NSArray *batchedNodes = [nodes subarrayWithRange:batchedRange]; - - [self _insertNodes:batchedNodes atIndexPaths:batchedIndexPaths withAnimationOption:animationOption]; - } -} - -- (void)insertRowsAtIndexPaths:(NSArray *)indexPaths withAnimationOption:(ASDataControllerAnimationOptions)animationOption -{ - [self performDataFetchingWithBlock:^{ + [self accessDataSourceWithBlock:^{ // sort indexPath to avoid messing up the index when inserting in several batches NSArray *sortedIndexPaths = [indexPaths sortedArrayUsingSelector:@selector(compare:)]; NSMutableArray *nodes = [[NSMutableArray alloc] initWithCapacity:indexPaths.count]; @@ -391,26 +479,26 @@ static void *kASSizingQueueContext = &kASSizingQueueContext; [nodes addObject:[_dataSource dataController:self nodeAtIndexPath:sortedIndexPaths[i]]]; } - [self _batchInsertNodes:nodes atIndexPaths:indexPaths withAnimationOptions:animationOption]; + [self _batchLayoutNodes:nodes atIndexPaths:indexPaths withAnimationOptions:animationOptions]; }]; } -- (void)deleteRowsAtIndexPaths:(NSArray *)indexPaths withAnimationOption:(ASDataControllerAnimationOptions)animationOption +- (void)deleteRowsAtIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions { // sort indexPath in order to avoid messing up the index when deleting NSArray *sortedIndexPaths = [indexPaths sortedArrayUsingSelector:@selector(compare:)]; dispatch_async([ASDataController sizingQueue], ^{ [self asyncUpdateDataWithBlock:^{ - DELETE_NODES(_nodes, sortedIndexPaths, animationOption); + [self _deleteNodesAtIndexPaths:sortedIndexPaths withAnimationOptions:animationOptions]; }]; }); } -- (void)reloadRowsAtIndexPaths:(NSArray *)indexPaths withAnimationOption:(ASDataControllerAnimationOptions)animationOption +- (void)reloadRowsAtIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions { // Reloading requires re-fetching the data. Load it on the current calling thread, locking the data source. - [self performDataFetchingWithBlock:^{ + [self accessDataSourceWithBlock:^{ NSMutableArray *nodes = [[NSMutableArray alloc] initWithCapacity:indexPaths.count]; [indexPaths sortedArrayUsingSelector:@selector(compare:)]; [indexPaths enumerateObjectsUsingBlock:^(NSIndexPath *indexPath, NSUInteger idx, BOOL *stop) { @@ -419,77 +507,30 @@ static void *kASSizingQueueContext = &kASSizingQueueContext; dispatch_async([ASDataController sizingQueue], ^{ [self syncUpdateDataWithBlock:^{ - DELETE_NODES(_nodes, indexPaths, animationOption); + [self _deleteNodesAtIndexPaths:indexPaths withAnimationOptions:animationOptions]; }]; - [self _batchInsertNodes:nodes atIndexPaths:indexPaths withAnimationOptions:animationOption]; + [self _batchLayoutNodes:nodes atIndexPaths:indexPaths withAnimationOptions:animationOptions]; }); }]; } -- (void)moveRowAtIndexPath:(NSIndexPath *)indexPath toIndexPath:(NSIndexPath *)newIndexPath withAnimationOption:(ASDataControllerAnimationOptions)animationOption +- (void)moveRowAtIndexPath:(NSIndexPath *)indexPath toIndexPath:(NSIndexPath *)newIndexPath withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions { dispatch_async([ASDataController sizingQueue], ^{ [self asyncUpdateDataWithBlock:^{ NSArray *nodes = ASFindElementsInMultidimensionalArrayAtIndexPaths(_nodes, [NSArray arrayWithObject:indexPath]); NSArray *indexPaths = [NSArray arrayWithObject:indexPath]; - DELETE_NODES(_nodes, indexPaths, animationOption); + [self _deleteNodesAtIndexPaths:indexPaths withAnimationOptions:animationOptions]; // Don't re-calculate size for moving NSArray *newIndexPaths = [NSArray arrayWithObject:newIndexPath]; - INSERT_NODES(_nodes, newIndexPaths, nodes, animationOption); + [self _insertNodes:nodes atIndexPaths:newIndexPaths withAnimationOptions:animationOptions]; }]; }); } -- (void)reloadDataWithAnimationOption:(ASDataControllerAnimationOptions)animationOption completion:(void (^)())completion -{ - [self performDataFetchingWithBlock:^{ - // Fetching data in calling thread - NSMutableArray *updatedNodes = [[NSMutableArray alloc] init]; - NSMutableArray *updatedIndexPaths = [[NSMutableArray alloc] init]; - - NSUInteger sectionNum = [_dataSource dataControllerNumberOfSections: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]; - [updatedIndexPaths addObject:indexPath]; - [updatedNodes addObject:[_dataSource dataController:self nodeAtIndexPath:indexPath]]; - } - } - - dispatch_async([ASDataController sizingQueue], ^{ - [self syncUpdateDataWithBlock:^{ - // Remove everything that existed before the reload, now that we're ready to insert replacements - NSArray *indexPaths = ASIndexPathsForMultidimensionalArray(_nodes); - DELETE_NODES(_nodes, indexPaths, animationOption); - - NSMutableIndexSet *indexSet = [[NSMutableIndexSet alloc] initWithIndexesInRange:NSMakeRange(0, _nodes.count)]; - DELETE_SECTIONS(_nodes, indexSet, animationOption); - - // Insert each section - NSMutableArray *sections = [[NSMutableArray alloc] initWithCapacity:sectionNum]; - for (int i = 0; i < sectionNum; i++) { - [sections addObject:[[NSMutableArray alloc] init]]; - } - - INSERT_SECTIONS(_nodes, [[NSMutableIndexSet alloc] initWithIndexesInRange:NSMakeRange(0, sectionNum)], sections, animationOption); - - }]; - - [self _batchInsertNodes:updatedNodes atIndexPaths:updatedIndexPaths withAnimationOptions:animationOption]; - - if (completion) { - dispatch_async(dispatch_get_main_queue(), completion); - } - }); - }]; -} - -#pragma mark - Data Querying +#pragma mark - Data Querying (External API) - (NSUInteger)numberOfSections { @@ -512,7 +553,7 @@ static void *kASSizingQueueContext = &kASSizingQueueContext; - (NSArray *)nodesAtIndexPaths:(NSArray *)indexPaths { ASDisplayNodeAssertMainThread(); - + // Make sure that any asynchronous layout operations have finished so that those nodes are present. // Otherwise a failure case could be: // - Reload section 2, deleting all current nodes in that section. diff --git a/AsyncDisplayKit/Details/ASRangeController.h b/AsyncDisplayKit/Details/ASRangeController.h index e78a2d3d22..f59b151f2e 100644 --- a/AsyncDisplayKit/Details/ASRangeController.h +++ b/AsyncDisplayKit/Details/ASRangeController.h @@ -90,43 +90,43 @@ /** * Called for nodes insertion. */ -- (void)rangeController:(ASRangeController *)rangeController didInsertNodesAtIndexPaths:(NSArray *)indexPaths withAnimationOption:(ASDataControllerAnimationOptions)animationOption; +- (void)rangeController:(ASRangeController *)rangeController didInsertNodesAtIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions; /** * Called for nodes deletion. */ -- (void)rangeController:(ASRangeController *)rangeController didDeleteNodesAtIndexPaths:(NSArray *)indexPaths withAnimationOption:(ASDataControllerAnimationOptions)animationOption; +- (void)rangeController:(ASRangeController *)rangeController didDeleteNodesAtIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions; /** * Called for section insertion. */ -- (void)rangeController:(ASRangeController *)rangeController didInsertSectionsAtIndexSet:(NSIndexSet *)indexSet withAnimationOption:(ASDataControllerAnimationOptions)animationOption; +- (void)rangeController:(ASRangeController *)rangeController didInsertSectionsAtIndexSet:(NSIndexSet *)indexSet withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions; /** * Called for section deletion. */ -- (void)rangeController:(ASRangeController *)rangeController didDeleteSectionsAtIndexSet:(NSIndexSet *)indexSet withAnimationOption:(ASDataControllerAnimationOptions)animationOption; +- (void)rangeController:(ASRangeController *)rangeController didDeleteSectionsAtIndexSet:(NSIndexSet *)indexSet withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions; @optional /** * Called before nodes insertion. */ -- (void)rangeController:(ASRangeController *)rangeController willInsertNodesAtIndexPaths:(NSArray *)indexPaths withAnimationOption:(ASDataControllerAnimationOptions)animationOption; +- (void)rangeController:(ASRangeController *)rangeController willInsertNodesAtIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions; /** * Called before nodes deletion. */ -- (void)rangeController:(ASRangeController *)rangeController willDeleteNodesAtIndexPaths:(NSArray *)indexPaths withAnimationOption:(ASDataControllerAnimationOptions)animationOption; +- (void)rangeController:(ASRangeController *)rangeController willDeleteNodesAtIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions; /** * Called before section insertion. */ -- (void)rangeController:(ASRangeController *)rangeController willInsertSectionsAtIndexSet:(NSIndexSet *)indexSet withAnimationOption:(ASDataControllerAnimationOptions)animationOption; +- (void)rangeController:(ASRangeController *)rangeController willInsertSectionsAtIndexSet:(NSIndexSet *)indexSet withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions; /** * Called before section deletion. */ -- (void)rangeController:(ASRangeController *)rangeController willDeleteSectionsAtIndexSet:(NSIndexSet *)indexSet withAnimationOption:(ASDataControllerAnimationOptions)animationOption; +- (void)rangeController:(ASRangeController *)rangeController willDeleteSectionsAtIndexSet:(NSIndexSet *)indexSet withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions; @end diff --git a/AsyncDisplayKit/Details/ASRangeController.mm b/AsyncDisplayKit/Details/ASRangeController.mm index 2a30ab362e..2ac2593da2 100644 --- a/AsyncDisplayKit/Details/ASRangeController.mm +++ b/AsyncDisplayKit/Details/ASRangeController.mm @@ -181,15 +181,15 @@ }); } -- (void)dataController:(ASDataController *)dataController willInsertNodes:(NSArray *)nodes atIndexPaths:(NSArray *)indexPaths withAnimationOption:(ASDataControllerAnimationOptions)animationOption { +- (void)dataController:(ASDataController *)dataController willInsertNodes:(NSArray *)nodes atIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions { ASDisplayNodePerformBlockOnMainThread(^{ - if ([_delegate respondsToSelector:@selector(rangeController:willInsertNodesAtIndexPaths:withAnimationOption:)]) { - [_delegate rangeController:self willInsertNodesAtIndexPaths:indexPaths withAnimationOption:animationOption]; + if ([_delegate respondsToSelector:@selector(rangeController:willInsertNodesAtIndexPaths:withAnimationOptions:)]) { + [_delegate rangeController:self willInsertNodesAtIndexPaths:indexPaths withAnimationOptions:animationOptions]; } }); } -- (void)dataController:(ASDataController *)dataController didInsertNodes:(NSArray *)nodes atIndexPaths:(NSArray *)indexPaths withAnimationOption:(ASDataControllerAnimationOptions)animationOption { +- (void)dataController:(ASDataController *)dataController didInsertNodes:(NSArray *)nodes atIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions { ASDisplayNodeAssert(nodes.count == indexPaths.count, @"Invalid index path"); NSMutableArray *nodeSizes = [NSMutableArray arrayWithCapacity:nodes.count]; @@ -202,37 +202,37 @@ [_layoutController insertNodesAtIndexPaths:indexPaths withSizes:nodeSizes]; } _rangeIsValid = NO; - [_delegate rangeController:self didInsertNodesAtIndexPaths:indexPaths withAnimationOption:animationOption]; + [_delegate rangeController:self didInsertNodesAtIndexPaths:indexPaths withAnimationOptions:animationOptions]; }); } -- (void)dataController:(ASDataController *)dataController willDeleteNodesAtIndexPaths:(NSArray *)indexPaths withAnimationOption:(ASDataControllerAnimationOptions)animationOption { +- (void)dataController:(ASDataController *)dataController willDeleteNodesAtIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions { ASDisplayNodePerformBlockOnMainThread(^{ - if ([_delegate respondsToSelector:@selector(rangeController:willDeleteNodesAtIndexPaths:withAnimationOption:)]) { - [_delegate rangeController:self willDeleteNodesAtIndexPaths:indexPaths withAnimationOption:animationOption]; + if ([_delegate respondsToSelector:@selector(rangeController:willDeleteNodesAtIndexPaths:withAnimationOptions:)]) { + [_delegate rangeController:self willDeleteNodesAtIndexPaths:indexPaths withAnimationOptions:animationOptions]; } }); } -- (void)dataController:(ASDataController *)dataController didDeleteNodesAtIndexPaths:(NSArray *)indexPaths withAnimationOption:(ASDataControllerAnimationOptions)animationOption { +- (void)dataController:(ASDataController *)dataController didDeleteNodesAtIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions { ASDisplayNodePerformBlockOnMainThread(^{ if ([_layoutController respondsToSelector:@selector(deleteNodesAtIndexPaths:)]) { [_layoutController deleteNodesAtIndexPaths:indexPaths]; } _rangeIsValid = NO; - [_delegate rangeController:self didDeleteNodesAtIndexPaths:indexPaths withAnimationOption:animationOption]; + [_delegate rangeController:self didDeleteNodesAtIndexPaths:indexPaths withAnimationOptions:animationOptions]; }); } -- (void)dataController:(ASDataController *)dataController willInsertSections:(NSArray *)sections atIndexSet:(NSIndexSet *)indexSet withAnimationOption:(ASDataControllerAnimationOptions)animationOption { +- (void)dataController:(ASDataController *)dataController willInsertSections:(NSArray *)sections atIndexSet:(NSIndexSet *)indexSet withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions { ASDisplayNodePerformBlockOnMainThread(^{ - if ([_delegate respondsToSelector:@selector(rangeController:willInsertSectionsAtIndexSet:withAnimationOption:)]) { - [_delegate rangeController:self willInsertSectionsAtIndexSet:indexSet withAnimationOption:animationOption]; + if ([_delegate respondsToSelector:@selector(rangeController:willInsertSectionsAtIndexSet:withAnimationOptions:)]) { + [_delegate rangeController:self willInsertSectionsAtIndexSet:indexSet withAnimationOptions:animationOptions]; } }); } -- (void)dataController:(ASDataController *)dataController didInsertSections:(NSArray *)sections atIndexSet:(NSIndexSet *)indexSet withAnimationOption:(ASDataControllerAnimationOptions)animationOption { +- (void)dataController:(ASDataController *)dataController didInsertSections:(NSArray *)sections atIndexSet:(NSIndexSet *)indexSet withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions { ASDisplayNodeAssert(sections.count == indexSet.count, @"Invalid sections"); NSMutableArray *sectionNodeSizes = [NSMutableArray arrayWithCapacity:sections.count]; @@ -250,25 +250,25 @@ [_layoutController insertSections:sectionNodeSizes atIndexSet:indexSet]; } _rangeIsValid = NO; - [_delegate rangeController:self didInsertSectionsAtIndexSet:indexSet withAnimationOption:animationOption]; + [_delegate rangeController:self didInsertSectionsAtIndexSet:indexSet withAnimationOptions:animationOptions]; }); } -- (void)dataController:(ASDataController *)dataController willDeleteSectionsAtIndexSet:(NSIndexSet *)indexSet withAnimationOption:(ASDataControllerAnimationOptions)animationOption { +- (void)dataController:(ASDataController *)dataController willDeleteSectionsAtIndexSet:(NSIndexSet *)indexSet withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions { ASDisplayNodePerformBlockOnMainThread(^{ - if ([_delegate respondsToSelector:@selector(rangeController:willDeleteSectionsAtIndexSet:withAnimationOption:)]) { - [_delegate rangeController:self willDeleteSectionsAtIndexSet:indexSet withAnimationOption:animationOption]; + if ([_delegate respondsToSelector:@selector(rangeController:willDeleteSectionsAtIndexSet:withAnimationOptions:)]) { + [_delegate rangeController:self willDeleteSectionsAtIndexSet:indexSet withAnimationOptions:animationOptions]; } }); } -- (void)dataController:(ASDataController *)dataController didDeleteSectionsAtIndexSet:(NSIndexSet *)indexSet withAnimationOption:(ASDataControllerAnimationOptions)animationOption { +- (void)dataController:(ASDataController *)dataController didDeleteSectionsAtIndexSet:(NSIndexSet *)indexSet withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions { ASDisplayNodePerformBlockOnMainThread(^{ if ([_layoutController respondsToSelector:@selector(deleteSectionsAtIndexSet:)]) { [_layoutController deleteSectionsAtIndexSet:indexSet]; } _rangeIsValid = NO; - [_delegate rangeController:self didDeleteSectionsAtIndexSet:indexSet withAnimationOption:animationOption]; + [_delegate rangeController:self didDeleteSectionsAtIndexSet:indexSet withAnimationOptions:animationOptions]; }); } diff --git a/AsyncDisplayKit/Details/ASTextNodeWordKerner.m b/AsyncDisplayKit/Details/ASTextNodeWordKerner.m index 0fd7d25004..ffd9655a91 100644 --- a/AsyncDisplayKit/Details/ASTextNodeWordKerner.m +++ b/AsyncDisplayKit/Details/ASTextNodeWordKerner.m @@ -90,7 +90,7 @@ static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ spaceSizes = [[NSMapTable alloc] initWithKeyOptions:NSMapTableStrongMemory valueOptions:NSMapTableStrongMemory capacity:1]; - mapQueue = dispatch_queue_create("com.facebook.AsyncDisplayKit.wordKerningQueue", DISPATCH_QUEUE_SERIAL); + mapQueue = dispatch_queue_create("org.AsyncDisplayKit.wordKerningQueue", DISPATCH_QUEUE_SERIAL); }); CGFloat ordinarySpaceWidth; UIFont *font = [layoutManager.textStorage attribute:NSFontAttributeName atIndex:characterIndex effectiveRange:NULL]; diff --git a/AsyncDisplayKit/Details/_ASDisplayLayer.mm b/AsyncDisplayKit/Details/_ASDisplayLayer.mm index 1acee3bd58..1d9b023983 100644 --- a/AsyncDisplayKit/Details/_ASDisplayLayer.mm +++ b/AsyncDisplayKit/Details/_ASDisplayLayer.mm @@ -129,7 +129,7 @@ static dispatch_queue_t displayQueue = NULL; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ - displayQueue = dispatch_queue_create("com.facebook.AsyncDisplayKit.ASDisplayLayer.displayQueue", DISPATCH_QUEUE_CONCURRENT); + displayQueue = dispatch_queue_create("org.AsyncDisplayKit.ASDisplayLayer.displayQueue", DISPATCH_QUEUE_CONCURRENT); // we use the highpri queue to prioritize UI rendering over other async operations dispatch_set_target_queue(displayQueue, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)); }); diff --git a/examples/ASTableViewStressTest/Sample/Info.plist b/examples/ASTableViewStressTest/Sample/Info.plist index 35d842827b..ad825d6e33 100644 --- a/examples/ASTableViewStressTest/Sample/Info.plist +++ b/examples/ASTableViewStressTest/Sample/Info.plist @@ -7,7 +7,7 @@ CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier - com.facebook.AsyncDisplayKit.$(PRODUCT_NAME:rfc1034identifier) + org.AsyncDisplayKit.$(PRODUCT_NAME:rfc1034identifier) CFBundleInfoDictionaryVersion 6.0 CFBundleName