diff --git a/AsyncDisplayKit/ASCollectionView.h b/AsyncDisplayKit/ASCollectionView.h index b99f55a7da..cb5bfd33dc 100644 --- a/AsyncDisplayKit/ASCollectionView.h +++ b/AsyncDisplayKit/ASCollectionView.h @@ -70,6 +70,15 @@ */ @property (nonatomic, assign) CGFloat leadingScreensForBatching; +/** + * Reload everything from scratch, destroying the working range and all cached nodes. + * + * @param completion block to run on completion of asynchronous loading or nil. If supplied, the block is run on + * the main thread. + * @warning This method is substantially more expensive than UICollectionView's version. + */ +- (void)reloadDataWithCompletion:(void (^)())completion; + /** * Reload everything from scratch, destroying the working range and all cached nodes. * diff --git a/AsyncDisplayKit/ASCollectionView.mm b/AsyncDisplayKit/ASCollectionView.mm index 80786df40d..04200238bf 100644 --- a/AsyncDisplayKit/ASCollectionView.mm +++ b/AsyncDisplayKit/ASCollectionView.mm @@ -162,13 +162,18 @@ - (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionVi #pragma mark - #pragma mark Overrides. -- (void)reloadData +- (void)reloadDataWithCompletion:(void (^)())completion { ASDisplayNodeAssert(self.asyncDelegate, @"ASCollectionView's asyncDelegate property must be set."); ASDisplayNodePerformBlockOnMainThread(^{ [super reloadData]; }); - [_dataController reloadDataWithAnimationOption:kASCollectionViewAnimationNone]; + [_dataController reloadDataWithAnimationOption:kASCollectionViewAnimationNone completion:completion]; +} + +- (void)reloadData +{ + [self reloadDataWithCompletion:nil]; } - (void)setDataSource:(id)dataSource diff --git a/AsyncDisplayKit/ASControlNode.m b/AsyncDisplayKit/ASControlNode.m index f423c33606..8a5d89ed11 100644 --- a/AsyncDisplayKit/ASControlNode.m +++ b/AsyncDisplayKit/ASControlNode.m @@ -226,7 +226,7 @@ - (void)addTarget:(id)target action:(SEL)action forControlEvents:(ASControlNodeE if (!eventDispatchTable) { // Create the dispatch table for this event. - eventDispatchTable = [NSMapTable strongToStrongObjectsMapTable]; + eventDispatchTable = [NSMapTable weakToStrongObjectsMapTable]; [_controlEventDispatchTable setObject:eventDispatchTable forKey:eventKey]; } diff --git a/AsyncDisplayKit/ASTableView.h b/AsyncDisplayKit/ASTableView.h index f783a5e880..8b399a01b4 100644 --- a/AsyncDisplayKit/ASTableView.h +++ b/AsyncDisplayKit/ASTableView.h @@ -70,6 +70,15 @@ */ @property (nonatomic, assign) CGFloat leadingScreensForBatching; +/** + * Reload everything from scratch, destroying the working range and all cached nodes. + * + * @param completion block to run on completion of asynchronous loading or nil. If supplied, the block is run on + * the main thread. + * @warning This method is substantially more expensive than UITableView's version. + */ +-(void)reloadDataWithCompletion:(void (^)())completion; + /** * Reload everything from scratch, destroying the working range and all cached nodes. * diff --git a/AsyncDisplayKit/ASTableView.mm b/AsyncDisplayKit/ASTableView.mm index d0a43aad39..63c7782a71 100644 --- a/AsyncDisplayKit/ASTableView.mm +++ b/AsyncDisplayKit/ASTableView.mm @@ -217,13 +217,18 @@ - (void)setAsyncDelegate:(id)asyncDelegate } } -- (void)reloadData +- (void)reloadDataWithCompletion:(void (^)())completion { ASDisplayNodeAssert(self.asyncDelegate, @"ASTableView's asyncDelegate property must be set."); ASDisplayNodePerformBlockOnMainThread(^{ [super reloadData]; }); - [_dataController reloadDataWithAnimationOption:UITableViewRowAnimationNone]; + [_dataController reloadDataWithAnimationOption:UITableViewRowAnimationNone completion:completion]; +} + +- (void)reloadData +{ + [self reloadDataWithCompletion:nil]; } - (void)setTuningParameters:(ASRangeTuningParameters)tuningParameters forRangeType:(ASLayoutRangeType)rangeType diff --git a/AsyncDisplayKit/Details/ASDataController.h b/AsyncDisplayKit/Details/ASDataController.h index 996d84427f..f8f8fca202 100644 --- a/AsyncDisplayKit/Details/ASDataController.h +++ b/AsyncDisplayKit/Details/ASDataController.h @@ -155,7 +155,7 @@ typedef NSUInteger ASDataControllerAnimationOptions; - (void)moveRowAtIndexPath:(NSIndexPath *)indexPath toIndexPath:(NSIndexPath *)newIndexPath withAnimationOption:(ASDataControllerAnimationOptions)animationOption;; -- (void)reloadDataWithAnimationOption:(ASDataControllerAnimationOptions)animationOption;; +- (void)reloadDataWithAnimationOption:(ASDataControllerAnimationOptions)animationOption completion:(void (^)())completion; /** @name Data Querying */ diff --git a/AsyncDisplayKit/Details/ASDataController.mm b/AsyncDisplayKit/Details/ASDataController.mm index ed70155727..8ba124286f 100644 --- a/AsyncDisplayKit/Details/ASDataController.mm +++ b/AsyncDisplayKit/Details/ASDataController.mm @@ -437,7 +437,7 @@ - (void)moveRowAtIndexPath:(NSIndexPath *)indexPath toIndexPath:(NSIndexPath *)n }); } -- (void)reloadDataWithAnimationOption:(ASDataControllerAnimationOptions)animationOption +- (void)reloadDataWithAnimationOption:(ASDataControllerAnimationOptions)animationOption completion:(void (^)())completion { [self performDataFetchingWithBlock:^{ // Fetching data in calling thread @@ -478,6 +478,10 @@ - (void)reloadDataWithAnimationOption:(ASDataControllerAnimationOptions)animatio }]; [self _batchInsertNodes:updatedNodes atIndexPaths:updatedIndexPaths withAnimationOptions:animationOption]; + + if (completion) { + dispatch_async(dispatch_get_main_queue(), completion); + } }); }]; }