diff --git a/AsyncDisplayKit/ASCollectionView.h b/AsyncDisplayKit/ASCollectionView.h index d65a900c..51319b98 100644 --- a/AsyncDisplayKit/ASCollectionView.h +++ b/AsyncDisplayKit/ASCollectionView.h @@ -34,6 +34,11 @@ */ @property (nonatomic, assign) ASRangeTuningParameters rangeTuningParameters; +/** + * Initializer. + */ +- (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout asyncDataFetching:(BOOL)asyncDataFetchingEnabled; + /** * Reload everything from scratch, destroying the working range and all cached nodes. * diff --git a/AsyncDisplayKit/ASCollectionView.mm b/AsyncDisplayKit/ASCollectionView.mm index ddd5ac25..88d10c3a 100644 --- a/AsyncDisplayKit/ASCollectionView.mm +++ b/AsyncDisplayKit/ASCollectionView.mm @@ -101,6 +101,8 @@ static BOOL _isInterceptedSelector(SEL sel) BOOL _performingBatchUpdates; NSMutableArray *_batchUpdateBlocks; + + BOOL _asyncDataFetchingEnabled; } @property (atomic, assign) BOOL asyncDataSourceLocked; @@ -113,6 +115,11 @@ static BOOL _isInterceptedSelector(SEL sel) #pragma mark Lifecycle. - (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout +{ + return [self initWithFrame:frame collectionViewLayout:layout asyncDataFetching:NO]; +} + +- (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout asyncDataFetching:(BOOL)asyncDataFetchingEnabled { if (!(self = [super initWithFrame:frame collectionViewLayout:layout])) return nil; @@ -126,13 +133,14 @@ static BOOL _isInterceptedSelector(SEL sel) _rangeController.delegate = self; _rangeController.layoutController = _layoutController; - _dataController = [[ASDataController alloc] init]; + _dataController = [[ASDataController alloc] initWithAsyncDataFetching:asyncDataFetchingEnabled]; _dataController.delegate = _rangeController; _dataController.dataSource = self; _proxyDelegate = [[_ASCollectionViewProxy alloc] initWithTarget:nil interceptor:self]; super.delegate = (id)_proxyDelegate; + _asyncDataFetchingEnabled = asyncDataFetchingEnabled; _asyncDataSourceLocked = NO; _performingBatchUpdates = NO; diff --git a/AsyncDisplayKit/ASTableView.h b/AsyncDisplayKit/ASTableView.h index e163bd69..6d4b111d 100644 --- a/AsyncDisplayKit/ASTableView.h +++ b/AsyncDisplayKit/ASTableView.h @@ -34,6 +34,11 @@ */ @property (nonatomic, assign) ASRangeTuningParameters rangeTuningParameters; +/** + * initializer. + */ +- (instancetype)initWithFrame:(CGRect)frame style:(UITableViewStyle)style asyncDataFetching:(BOOL)asyncDataFetchingEnabled; + /** * Reload everything from scratch, destroying the working range and all cached nodes. * diff --git a/AsyncDisplayKit/ASTableView.mm b/AsyncDisplayKit/ASTableView.mm index 2c2c43cf..758782f7 100644 --- a/AsyncDisplayKit/ASTableView.mm +++ b/AsyncDisplayKit/ASTableView.mm @@ -110,6 +110,8 @@ static BOOL _isInterceptedSelector(SEL sel) ASFlowLayoutController *_layoutController; ASRangeController *_rangeController; + + BOOL _asyncDataFetchingEnabled; } @property (atomic, assign) BOOL asyncDataSouceLocked; @@ -123,6 +125,12 @@ static BOOL _isInterceptedSelector(SEL sel) - (instancetype)initWithFrame:(CGRect)frame style:(UITableViewStyle)style { + return [self initWithFrame:frame style:style asyncDataFetching:NO]; +} + +- (instancetype)initWithFrame:(CGRect)frame style:(UITableViewStyle)style asyncDataFetching:(BOOL)asyncDataFetchingEnabled +{ + if (!(self = [super initWithFrame:frame style:style])) return nil; @@ -132,13 +140,14 @@ static BOOL _isInterceptedSelector(SEL sel) _rangeController.layoutController = _layoutController; _rangeController.delegate = self; - _dataController = [[ASDataController alloc] init]; + _dataController = [[ASDataController alloc] initWithAsyncDataFetching:asyncDataFetchingEnabled]; _dataController.dataSource = self; _dataController.delegate = _rangeController; _proxyDelegate = [[_ASTableViewProxy alloc] initWithTarget:nil interceptor:self]; super.delegate = (id)_proxyDelegate; + _asyncDataFetchingEnabled = asyncDataFetchingEnabled; _asyncDataSouceLocked = NO; return self; @@ -168,6 +177,9 @@ static BOOL _isInterceptedSelector(SEL sel) _proxyDataSource = nil; super.dataSource = nil; } else { + ASDisplayNodeAssert(!_asyncDataFetchingEnabled || ([asyncDataSource respondsToSelector:@selector(tableViewLockDataSourceForDataUpdating:)] && + [asyncDataSource respondsToSelector:@selector(tableViewUnlockDataSourceForDataUpdating:)]), + @"The asyncDataSource need to implements \"tableViewLockDataSourceForDataUpdating\" and \"tableViewUnlockDataSourceForDataUpdating\" to handle data fetching in async mode."); _asyncDataSource = asyncDataSource; _proxyDataSource = [[_ASTableViewProxy alloc] initWithTarget:_asyncDataSource interceptor:self]; super.dataSource = (id)_proxyDataSource; diff --git a/AsyncDisplayKit/Details/ASDataController.h b/AsyncDisplayKit/Details/ASDataController.h index f493eee2..5825982f 100644 --- a/AsyncDisplayKit/Details/ASDataController.h +++ b/AsyncDisplayKit/Details/ASDataController.h @@ -119,6 +119,11 @@ typedef NSUInteger ASDataControllerAnimationOptions; */ @property (nonatomic, weak) id delegate; +/** + Designated iniailizer. + */ +- (instancetype)initWithAsyncDataFetching:(BOOL)asyncDataFetchingEnabled; + /** @name Initial loading */ - (void)initialDataLoadingWithAnimationOption:(ASDataControllerAnimationOptions)animationOption; diff --git a/AsyncDisplayKit/Details/ASDataController.mm b/AsyncDisplayKit/Details/ASDataController.mm index 78356e94..6e400d7c 100644 --- a/AsyncDisplayKit/Details/ASDataController.mm +++ b/AsyncDisplayKit/Details/ASDataController.mm @@ -12,11 +12,18 @@ #ifdef ENABLE_ASYNC_DATA_FETCHING #define BEGIN_DATA_FETCHING \ - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ \ - [_dataSource dataControllerLockDataSourceForDataUpdating]; + dispatch_block_t block = ^{ #define END_DATA_FETCHING \ - [_dataSource dataControllerUnlockDataSourceForDataUpdating]; \ - }); + }; \ + if (_asyncDataFetchingEnabled) { \ + [_dataSource dataControllerLockDataSourceForDataUpdating]; \ + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ \ + block(); \ + [_dataSource dataControllerUnlockDataSourceForDataUpdating]; \ + }); \ + } else { \ + block(); \ + } #else #define BEGIN_DATA_FETCHING #define END_DATA_FETCHING @@ -73,6 +80,7 @@ static void *kASSizingQueueContext = &kASSizingQueueContext; @interface ASDataController () { NSMutableArray *_nodes; NSMutableArray *_pendingBlocks; + BOOL _asyncDataFetchingEnabled; } @property (atomic, assign) NSUInteger batchUpdateCounter; @@ -81,11 +89,12 @@ static void *kASSizingQueueContext = &kASSizingQueueContext; @implementation ASDataController -- (instancetype)init { +- (instancetype)initWithAsyncDataFetching:(BOOL)asyncDataFetchingEnabled { if (self = [super init]) { _nodes = [NSMutableArray array]; _pendingBlocks = [NSMutableArray array]; _batchUpdateCounter = 0; + _asyncDataFetchingEnabled = asyncDataFetchingEnabled; } return self; @@ -143,8 +152,7 @@ static void *kASSizingQueueContext = &kASSizingQueueContext; #pragma mark - Initial Data Loading -- (void)initialDataLoadingWithAnimationOption:(ASDataControllerAnimationOptions)animationOption -{ +- (void)initialDataLoadingWithAnimationOption:(ASDataControllerAnimationOptions)animationOption { BEGIN_DATA_FETCHING NSMutableArray *indexPaths = [NSMutableArray array];