mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-22 14:20:20 +00:00
Merge branch 'master' into update-objc
Conflicts: AsyncDisplayKit/ASCollectionView.h AsyncDisplayKit/ASTableView.h AsyncDisplayKit/Details/ASLayoutController.h AsyncDisplayKit/Details/ASRangeController.h
This commit is contained in:
@@ -433,10 +433,4 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@interface ASCollectionView (Deprecated)
|
|
||||||
|
|
||||||
@property (nonatomic, assign) ASRangeTuningParameters rangeTuningParameters ASDISPLAYNODE_DEPRECATED;
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
||||||
NS_ASSUME_NONNULL_END
|
NS_ASSUME_NONNULL_END
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ static BOOL _isInterceptedSelector(SEL sel)
|
|||||||
#pragma mark -
|
#pragma mark -
|
||||||
#pragma mark ASCollectionView.
|
#pragma mark ASCollectionView.
|
||||||
|
|
||||||
@interface ASCollectionView () <ASRangeControllerDelegate, ASDataControllerSource, ASCellNodeLayoutDelegate> {
|
@interface ASCollectionView () <ASRangeControllerDataSource, ASRangeControllerDelegate, ASDataControllerSource, ASCellNodeLayoutDelegate> {
|
||||||
_ASCollectionViewProxy *_proxyDataSource;
|
_ASCollectionViewProxy *_proxyDataSource;
|
||||||
_ASCollectionViewProxy *_proxyDelegate;
|
_ASCollectionViewProxy *_proxyDelegate;
|
||||||
|
|
||||||
@@ -199,6 +199,7 @@ static BOOL _isInterceptedSelector(SEL sel)
|
|||||||
_layoutController = [[ASCollectionViewLayoutController alloc] initWithCollectionView:self];
|
_layoutController = [[ASCollectionViewLayoutController alloc] initWithCollectionView:self];
|
||||||
|
|
||||||
_rangeController = [[ASRangeController alloc] init];
|
_rangeController = [[ASRangeController alloc] init];
|
||||||
|
_rangeController.dataSource = self;
|
||||||
_rangeController.delegate = self;
|
_rangeController.delegate = self;
|
||||||
_rangeController.layoutController = _layoutController;
|
_rangeController.layoutController = _layoutController;
|
||||||
|
|
||||||
@@ -767,14 +768,35 @@ static BOOL _isInterceptedSelector(SEL sel)
|
|||||||
return [_layoutInspector collectionView:self numberOfSectionsForSupplementaryNodeOfKind:kind];
|
return [_layoutInspector collectionView:self numberOfSectionsForSupplementaryNodeOfKind:kind];
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - ASRangeControllerDelegate.
|
#pragma mark - ASRangeControllerDataSource
|
||||||
|
|
||||||
- (void)rangeControllerBeginUpdates:(ASRangeController *)rangeController {
|
- (NSArray *)visibleNodeIndexPathsForRangeController:(ASRangeController *)rangeController
|
||||||
|
{
|
||||||
|
ASDisplayNodeAssertMainThread();
|
||||||
|
return [self indexPathsForVisibleItems];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (CGSize)viewportSizeForRangeController:(ASRangeController *)rangeController
|
||||||
|
{
|
||||||
|
ASDisplayNodeAssertMainThread();
|
||||||
|
return self.bounds.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSArray *)rangeController:(ASRangeController *)rangeController nodesAtIndexPaths:(NSArray *)indexPaths
|
||||||
|
{
|
||||||
|
return [_dataController nodesAtIndexPaths:indexPaths];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - ASRangeControllerDelegate
|
||||||
|
|
||||||
|
- (void)didBeginUpdatesInRangeController:(ASRangeController *)rangeController
|
||||||
|
{
|
||||||
ASDisplayNodeAssertMainThread();
|
ASDisplayNodeAssertMainThread();
|
||||||
_performingBatchUpdates = YES;
|
_performingBatchUpdates = YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)rangeController:(ASRangeController *)rangeController endUpdatesAnimated:(BOOL)animated completion:(void (^)(BOOL))completion {
|
- (void)rangeController:(ASRangeController *)rangeController didEndUpdatesAnimated:(BOOL)animated completion:(void (^)(BOOL))completion
|
||||||
|
{
|
||||||
ASDisplayNodeAssertMainThread();
|
ASDisplayNodeAssertMainThread();
|
||||||
|
|
||||||
if (!self.asyncDataSource || _superIsPendingDataLoad) {
|
if (!self.asyncDataSource || _superIsPendingDataLoad) {
|
||||||
@@ -796,23 +818,6 @@ static BOOL _isInterceptedSelector(SEL sel)
|
|||||||
_performingBatchUpdates = NO;
|
_performingBatchUpdates = NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSArray *)rangeControllerVisibleNodeIndexPaths:(ASRangeController *)rangeController
|
|
||||||
{
|
|
||||||
ASDisplayNodeAssertMainThread();
|
|
||||||
return [self indexPathsForVisibleItems];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (CGSize)rangeControllerViewportSize:(ASRangeController *)rangeController
|
|
||||||
{
|
|
||||||
ASDisplayNodeAssertMainThread();
|
|
||||||
return self.bounds.size;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSArray *)rangeController:(ASRangeController *)rangeController nodesAtIndexPaths:(NSArray *)indexPaths
|
|
||||||
{
|
|
||||||
return [_dataController nodesAtIndexPaths:indexPaths];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)rangeController:(ASRangeController *)rangeController didInsertNodes:(NSArray *)nodes atIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions
|
- (void)rangeController:(ASRangeController *)rangeController didInsertNodes:(NSArray *)nodes atIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions
|
||||||
{
|
{
|
||||||
ASDisplayNodeAssertMainThread();
|
ASDisplayNodeAssertMainThread();
|
||||||
|
|||||||
@@ -1644,7 +1644,8 @@ void recursivelyEnsureDisplayForLayer(CALayer *layer)
|
|||||||
|
|
||||||
- (void)clearContents
|
- (void)clearContents
|
||||||
{
|
{
|
||||||
self.layer.contents = nil;
|
// No-op if these haven't been created yet, as that guarantees they don't have contents that needs to be released.
|
||||||
|
_layer.contents = nil;
|
||||||
_placeholderLayer.contents = nil;
|
_placeholderLayer.contents = nil;
|
||||||
_placeholderImage = nil;
|
_placeholderImage = nil;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
#import "ASDisplayNode+Subclasses.h"
|
#import "ASDisplayNode+Subclasses.h"
|
||||||
#import "ASLog.h"
|
#import "ASLog.h"
|
||||||
#import "ASPhotosFrameworkImageRequest.h"
|
#import "ASPhotosFrameworkImageRequest.h"
|
||||||
|
#import "ASEqualityHelpers.h"
|
||||||
|
|
||||||
#if !AS_IOS8_SDK_OR_LATER
|
#if !AS_IOS8_SDK_OR_LATER
|
||||||
#error ASMultiplexImageNode can be used on iOS 7, but must be linked against the iOS 8 SDK.
|
#error ASMultiplexImageNode can be used on iOS 7, but must be linked against the iOS 8 SDK.
|
||||||
@@ -176,17 +177,13 @@ typedef void(^ASMultiplexImageLoadCompletionBlock)(UIImage *image, id imageIdent
|
|||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - ASDisplayNode Overrides
|
#pragma mark - ASDisplayNode Overrides
|
||||||
|
|
||||||
- (void)clearContents
|
- (void)clearContents
|
||||||
{
|
{
|
||||||
[super clearContents]; // This actually clears the contents, so we need to do this first for our displayedImageIdentifier to be meaningful.
|
[super clearContents]; // This actually clears the contents, so we need to do this first for our displayedImageIdentifier to be meaningful.
|
||||||
[self _setDisplayedImageIdentifier:nil withImage:nil];
|
[self _setDisplayedImageIdentifier:nil withImage:nil];
|
||||||
|
|
||||||
[_phImageRequestOperation cancel];
|
// NOTE: We intentionally do not cancel image downloads until `clearFetchedData`.
|
||||||
|
|
||||||
if (_downloadIdentifier) {
|
|
||||||
[_downloader cancelImageDownloadForIdentifier:_downloadIdentifier];
|
|
||||||
_downloadIdentifier = nil;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)clearFetchedData
|
- (void)clearFetchedData
|
||||||
@@ -196,12 +193,9 @@ typedef void(^ASMultiplexImageLoadCompletionBlock)(UIImage *image, id imageIdent
|
|||||||
if ([self _shouldClearFetchedImageData]) {
|
if ([self _shouldClearFetchedImageData]) {
|
||||||
|
|
||||||
[_phImageRequestOperation cancel];
|
[_phImageRequestOperation cancel];
|
||||||
|
|
||||||
if (_downloadIdentifier) {
|
[self _setDownloadIdentifier:nil];
|
||||||
[_downloader cancelImageDownloadForIdentifier:_downloadIdentifier];
|
|
||||||
_downloadIdentifier = nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
// setting this to nil makes the node fetch images the next time its display starts
|
// setting this to nil makes the node fetch images the next time its display starts
|
||||||
_loadedImageIdentifier = nil;
|
_loadedImageIdentifier = nil;
|
||||||
self.image = nil;
|
self.image = nil;
|
||||||
@@ -222,7 +216,7 @@ typedef void(^ASMultiplexImageLoadCompletionBlock)(UIImage *image, id imageIdent
|
|||||||
// We may now be displaying the loaded identifier, if they're different.
|
// We may now be displaying the loaded identifier, if they're different.
|
||||||
UIImage *displayedImage = self.image;
|
UIImage *displayedImage = self.image;
|
||||||
if (displayedImage) {
|
if (displayedImage) {
|
||||||
if (![_displayedImageIdentifier isEqual:_loadedImageIdentifier])
|
if (!ASObjectIsEqual(_displayedImageIdentifier, _loadedImageIdentifier))
|
||||||
[self _setDisplayedImageIdentifier:_loadedImageIdentifier withImage:displayedImage];
|
[self _setDisplayedImageIdentifier:_loadedImageIdentifier withImage:displayedImage];
|
||||||
|
|
||||||
// Delegateify
|
// Delegateify
|
||||||
@@ -286,7 +280,7 @@ typedef void(^ASMultiplexImageLoadCompletionBlock)(UIImage *image, id imageIdent
|
|||||||
{
|
{
|
||||||
OSSpinLockLock(&_imageIdentifiersLock);
|
OSSpinLockLock(&_imageIdentifiersLock);
|
||||||
|
|
||||||
if ([_imageIdentifiers isEqual:imageIdentifiers]) {
|
if (ASObjectIsEqual(_imageIdentifiers, imageIdentifiers)) {
|
||||||
OSSpinLockUnlock(&_imageIdentifiersLock);
|
OSSpinLockUnlock(&_imageIdentifiersLock);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -308,7 +302,7 @@ typedef void(^ASMultiplexImageLoadCompletionBlock)(UIImage *image, id imageIdent
|
|||||||
#pragma mark - Core Internal
|
#pragma mark - Core Internal
|
||||||
- (void)_setDisplayedImageIdentifier:(id)displayedImageIdentifier withImage:(UIImage *)image
|
- (void)_setDisplayedImageIdentifier:(id)displayedImageIdentifier withImage:(UIImage *)image
|
||||||
{
|
{
|
||||||
if (_displayedImageIdentifier == displayedImageIdentifier)
|
if (ASObjectIsEqual(displayedImageIdentifier, _displayedImageIdentifier))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_displayedImageIdentifier = [displayedImageIdentifier copy];
|
_displayedImageIdentifier = [displayedImageIdentifier copy];
|
||||||
@@ -332,7 +326,7 @@ typedef void(^ASMultiplexImageLoadCompletionBlock)(UIImage *image, id imageIdent
|
|||||||
|
|
||||||
- (void)_setDownloadIdentifier:(id)downloadIdentifier
|
- (void)_setDownloadIdentifier:(id)downloadIdentifier
|
||||||
{
|
{
|
||||||
if (_downloadIdentifier == downloadIdentifier)
|
if (ASObjectIsEqual(downloadIdentifier, _downloadIdentifier))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
[_downloader cancelImageDownloadForIdentifier:_downloadIdentifier];
|
[_downloader cancelImageDownloadForIdentifier:_downloadIdentifier];
|
||||||
@@ -391,7 +385,7 @@ typedef void(^ASMultiplexImageLoadCompletionBlock)(UIImage *image, id imageIdent
|
|||||||
|
|
||||||
// If we've already loaded the best identifier, we've got nothing else to do.
|
// If we've already loaded the best identifier, we've got nothing else to do.
|
||||||
id bestImageIdentifier = _imageIdentifiers.firstObject;
|
id bestImageIdentifier = _imageIdentifiers.firstObject;
|
||||||
if (!bestImageIdentifier || [_loadedImageIdentifier isEqual:bestImageIdentifier]) {
|
if (!bestImageIdentifier || ASObjectIsEqual(_loadedImageIdentifier, bestImageIdentifier)) {
|
||||||
OSSpinLockUnlock(&_imageIdentifiersLock);
|
OSSpinLockUnlock(&_imageIdentifiersLock);
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
@@ -439,7 +433,7 @@ typedef void(^ASMultiplexImageLoadCompletionBlock)(UIImage *image, id imageIdent
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// Only nil out the loading identifier if the loading identifier hasn't changed.
|
// Only nil out the loading identifier if the loading identifier hasn't changed.
|
||||||
if ([strongSelf.loadingImageIdentifier isEqual:nextImageIdentifier]) {
|
if (ASObjectIsEqual(strongSelf.loadingImageIdentifier, nextImageIdentifier)) {
|
||||||
strongSelf.loadingImageIdentifier = nil;
|
strongSelf.loadingImageIdentifier = nil;
|
||||||
}
|
}
|
||||||
[strongSelf _finishedLoadingImage:image forIdentifier:imageIdentifier error:error];
|
[strongSelf _finishedLoadingImage:image forIdentifier:imageIdentifier error:error];
|
||||||
@@ -496,7 +490,7 @@ typedef void(^ASMultiplexImageLoadCompletionBlock)(UIImage *image, id imageIdent
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If the next image to load has changed, bail.
|
// If the next image to load has changed, bail.
|
||||||
if (![[strongSelf _nextImageIdentifierToDownload] isEqual:nextImageIdentifier]) {
|
if (!ASObjectIsEqual([strongSelf _nextImageIdentifierToDownload], nextImageIdentifier)) {
|
||||||
finishedLoadingBlock(nil, nil, [NSError errorWithDomain:ASMultiplexImageNodeErrorDomain code:ASMultiplexImageNodeErrorCodeBestImageIdentifierChanged userInfo:nil]);
|
finishedLoadingBlock(nil, nil, [NSError errorWithDomain:ASMultiplexImageNodeErrorDomain code:ASMultiplexImageNodeErrorCodeBestImageIdentifierChanged userInfo:nil]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -361,10 +361,4 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@interface ASTableView (Deprecated)
|
|
||||||
|
|
||||||
@property (nonatomic, assign) ASRangeTuningParameters rangeTuningParameters ASDISPLAYNODE_DEPRECATED;
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
||||||
NS_ASSUME_NONNULL_END
|
NS_ASSUME_NONNULL_END
|
||||||
|
|||||||
@@ -151,7 +151,7 @@ static BOOL _isInterceptedSelector(SEL sel)
|
|||||||
#pragma mark -
|
#pragma mark -
|
||||||
#pragma mark ASTableView
|
#pragma mark ASTableView
|
||||||
|
|
||||||
@interface ASTableView () <ASRangeControllerDelegate, ASDataControllerSource, _ASTableViewCellDelegate, ASCellNodeLayoutDelegate> {
|
@interface ASTableView () <ASRangeControllerDataSource, ASRangeControllerDelegate, ASDataControllerSource, _ASTableViewCellDelegate, ASCellNodeLayoutDelegate> {
|
||||||
_ASTableViewProxy *_proxyDataSource;
|
_ASTableViewProxy *_proxyDataSource;
|
||||||
_ASTableViewProxy *_proxyDelegate;
|
_ASTableViewProxy *_proxyDelegate;
|
||||||
|
|
||||||
@@ -193,6 +193,7 @@ static BOOL _isInterceptedSelector(SEL sel)
|
|||||||
|
|
||||||
_rangeController = [[ASRangeController alloc] init];
|
_rangeController = [[ASRangeController alloc] init];
|
||||||
_rangeController.layoutController = _layoutController;
|
_rangeController.layoutController = _layoutController;
|
||||||
|
_rangeController.dataSource = self;
|
||||||
_rangeController.delegate = self;
|
_rangeController.delegate = self;
|
||||||
|
|
||||||
_dataController = [[dataControllerClass alloc] initWithAsyncDataFetching:asyncDataFetching];
|
_dataController = [[dataControllerClass alloc] initWithAsyncDataFetching:asyncDataFetching];
|
||||||
@@ -639,11 +640,72 @@ static BOOL _isInterceptedSelector(SEL sel)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma mark - ASRangeControllerDataSource
|
||||||
|
|
||||||
#pragma mark -
|
- (NSArray *)visibleNodeIndexPathsForRangeController:(ASRangeController *)rangeController
|
||||||
#pragma mark ASRangeControllerDelegate
|
{
|
||||||
|
ASDisplayNodeAssertMainThread();
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
- (void)rangeControllerBeginUpdates:(ASRangeController *)rangeController
|
- (NSArray *)rangeController:(ASRangeController *)rangeController nodesAtIndexPaths:(NSArray *)indexPaths
|
||||||
|
{
|
||||||
|
return [_dataController nodesAtIndexPaths:indexPaths];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (CGSize)viewportSizeForRangeController:(ASRangeController *)rangeController
|
||||||
|
{
|
||||||
|
ASDisplayNodeAssertMainThread();
|
||||||
|
return self.bounds.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - ASRangeControllerDelegate
|
||||||
|
|
||||||
|
- (void)didBeginUpdatesInRangeController:(ASRangeController *)rangeController
|
||||||
{
|
{
|
||||||
ASDisplayNodeAssertMainThread();
|
ASDisplayNodeAssertMainThread();
|
||||||
LOG(@"--- UITableView beginUpdates");
|
LOG(@"--- UITableView beginUpdates");
|
||||||
@@ -659,7 +721,7 @@ static BOOL _isInterceptedSelector(SEL sel)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)rangeController:(ASRangeController *)rangeController endUpdatesAnimated:(BOOL)animated completion:(void (^)(BOOL))completion
|
- (void)rangeController:(ASRangeController *)rangeController didEndUpdatesAnimated:(BOOL)animated completion:(void (^)(BOOL))completion
|
||||||
{
|
{
|
||||||
ASDisplayNodeAssertMainThread();
|
ASDisplayNodeAssertMainThread();
|
||||||
LOG(@"--- UITableView endUpdates");
|
LOG(@"--- UITableView endUpdates");
|
||||||
@@ -684,67 +746,6 @@ static BOOL _isInterceptedSelector(SEL sel)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSArray *)rangeControllerVisibleNodeIndexPaths:(ASRangeController *)rangeController
|
|
||||||
{
|
|
||||||
ASDisplayNodeAssertMainThread();
|
|
||||||
|
|
||||||
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
|
|
||||||
{
|
|
||||||
return [_dataController nodesAtIndexPaths:indexPaths];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (CGSize)rangeControllerViewportSize:(ASRangeController *)rangeController
|
|
||||||
{
|
|
||||||
ASDisplayNodeAssertMainThread();
|
|
||||||
return self.bounds.size;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)rangeController:(ASRangeController *)rangeController didInsertNodes:(NSArray *)nodes atIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions
|
- (void)rangeController:(ASRangeController *)rangeController didInsertNodes:(NSArray *)nodes atIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions
|
||||||
{
|
{
|
||||||
ASDisplayNodeAssertMainThread();
|
ASDisplayNodeAssertMainThread();
|
||||||
|
|||||||
@@ -17,8 +17,6 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
|
|
||||||
- (ASRangeTuningParameters)tuningParametersForRangeType:(ASLayoutRangeType)rangeType;
|
- (ASRangeTuningParameters)tuningParametersForRangeType:(ASLayoutRangeType)rangeType;
|
||||||
|
|
||||||
@property (nonatomic, assign) ASRangeTuningParameters tuningParameters ASDISPLAYNODE_DEPRECATED;
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
NS_ASSUME_NONNULL_END
|
NS_ASSUME_NONNULL_END
|
||||||
|
|||||||
@@ -52,33 +52,7 @@
|
|||||||
_tuningParameters[rangeType] = tuningParameters;
|
_tuningParameters[rangeType] = tuningParameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Support for the deprecated tuningParameters property
|
#pragma mark - Abstract Index Path Range Support
|
||||||
- (ASRangeTuningParameters)tuningParameters
|
|
||||||
{
|
|
||||||
return [self tuningParametersForRangeType:ASLayoutRangeTypeRender];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Support for the deprecated tuningParameters property
|
|
||||||
- (void)setTuningParameters:(ASRangeTuningParameters)tuningParameters
|
|
||||||
{
|
|
||||||
[self setTuningParameters:tuningParameters forRangeType:ASLayoutRangeTypeRender];
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma mark - Index Path Range Support
|
|
||||||
|
|
||||||
// Support for deprecated method
|
|
||||||
- (BOOL)shouldUpdateForVisibleIndexPath:(NSArray *)indexPaths viewportSize:(CGSize)viewportSize
|
|
||||||
{
|
|
||||||
return [self shouldUpdateForVisibleIndexPaths:indexPaths viewportSize:viewportSize rangeType:ASLayoutRangeTypeRender];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Support for the deprecated method
|
|
||||||
- (NSSet *)indexPathsForScrolling:(ASScrollDirection)scrollDirection viewportSize:(CGSize)viewportSize
|
|
||||||
{
|
|
||||||
return [self indexPathsForScrolling:scrollDirection viewportSize:viewportSize rangeType:ASLayoutRangeTypeRender];
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma mark - Abstract
|
|
||||||
|
|
||||||
- (BOOL)shouldUpdateForVisibleIndexPaths:(NSArray *)indexPaths viewportSize:(CGSize)viewportSize rangeType:(ASLayoutRangeType)rangeType
|
- (BOOL)shouldUpdateForVisibleIndexPaths:(NSArray *)indexPaths viewportSize:(CGSize)viewportSize rangeType:(ASLayoutRangeType)rangeType
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -14,8 +14,6 @@
|
|||||||
|
|
||||||
NS_ASSUME_NONNULL_BEGIN
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
@class ASCellNode;
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
CGFloat leadingBufferScreenfuls;
|
CGFloat leadingBufferScreenfuls;
|
||||||
CGFloat trailingBufferScreenfuls;
|
CGFloat trailingBufferScreenfuls;
|
||||||
@@ -34,12 +32,6 @@ typedef struct {
|
|||||||
|
|
||||||
- (NSSet *)indexPathsForScrolling:(ASScrollDirection)scrollDirection viewportSize:(CGSize)viewportSize rangeType:(ASLayoutRangeType)rangeType;
|
- (NSSet *)indexPathsForScrolling:(ASScrollDirection)scrollDirection viewportSize:(CGSize)viewportSize rangeType:(ASLayoutRangeType)rangeType;
|
||||||
|
|
||||||
@property (nonatomic, assign) ASRangeTuningParameters tuningParameters ASDISPLAYNODE_DEPRECATED;
|
|
||||||
|
|
||||||
- (BOOL)shouldUpdateForVisibleIndexPath:(NSIndexPath *)indexPath viewportSize:(CGSize)viewportSize ASDISPLAYNODE_DEPRECATED;
|
|
||||||
|
|
||||||
- (NSSet *)indexPathsForScrolling:(ASScrollDirection)scrollDirection viewportSize:(CGSize)viewportSize ASDISPLAYNODE_DEPRECATED;
|
|
||||||
|
|
||||||
@optional
|
@optional
|
||||||
|
|
||||||
- (void)insertNodesAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths withSizes:(NSArray<NSValue *> *)nodeSizes;
|
- (void)insertNodesAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths withSizes:(NSArray<NSValue *> *)nodeSizes;
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
NS_ASSUME_NONNULL_BEGIN
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@protocol ASRangeControllerDataSource;
|
||||||
@protocol ASRangeControllerDelegate;
|
@protocol ASRangeControllerDelegate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -47,49 +48,46 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
- (void)configureContentView:(UIView *)contentView forCellNode:(ASCellNode *)node;
|
- (void)configureContentView:(UIView *)contentView forCellNode:(ASCellNode *)node;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delegate and ultimate data source. Must not be nil.
|
* An object that describes the layout behavior of the ranged component (table view, collection view, etc.)
|
||||||
|
*
|
||||||
|
* Used primarily for providing the current range of index paths and identifying when the
|
||||||
|
* range controller should invalidate its range.
|
||||||
|
*/
|
||||||
|
@property (nonatomic, strong) id<ASLayoutController> layoutController;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The underlying data source for the range controller
|
||||||
|
*/
|
||||||
|
@property (nonatomic, weak) id<ASRangeControllerDataSource> dataSource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delegate for handling range controller events. Must not be nil.
|
||||||
*/
|
*/
|
||||||
@property (nonatomic, weak) id<ASRangeControllerDelegate> delegate;
|
@property (nonatomic, weak) id<ASRangeControllerDelegate> delegate;
|
||||||
|
|
||||||
@property (nonatomic, strong) id<ASLayoutController> layoutController;
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <ASRangeController> delegate. For example, <ASTableView>.
|
* Data source for ASRangeController.
|
||||||
|
*
|
||||||
|
* Allows the range controller to perform external queries on the range.
|
||||||
|
* Ex. range nodes, visible index paths, and viewport size.
|
||||||
*/
|
*/
|
||||||
@protocol ASRangeControllerDelegate <NSObject>
|
@protocol ASRangeControllerDataSource <NSObject>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param rangeController Sender.
|
* @param rangeController Sender.
|
||||||
*
|
*
|
||||||
* @returns an array of index paths corresponding to the nodes currently visible onscreen (i.e., the visible range).
|
* @returns an array of index paths corresponding to the nodes currently visible onscreen (i.e., the visible range).
|
||||||
*/
|
*/
|
||||||
- (NSArray<NSIndexPath *> *)rangeControllerVisibleNodeIndexPaths:(ASRangeController *)rangeController;
|
- (NSArray<NSIndexPath *> *)visibleNodeIndexPathsForRangeController:(ASRangeController *)rangeController;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param rangeController Sender.
|
* @param rangeController Sender.
|
||||||
*
|
*
|
||||||
* @returns the receiver's viewport size (i.e., the screen space occupied by the visible range).
|
* @returns the receiver's viewport size (i.e., the screen space occupied by the visible range).
|
||||||
*/
|
*/
|
||||||
- (CGSize)rangeControllerViewportSize:(ASRangeController *)rangeController;
|
- (CGSize)viewportSizeForRangeController:(ASRangeController *)rangeController;
|
||||||
|
|
||||||
/**
|
|
||||||
* Begin updates.
|
|
||||||
*
|
|
||||||
* @param rangeController Sender.
|
|
||||||
*/
|
|
||||||
- (void)rangeControllerBeginUpdates:(ASRangeController *)rangeController;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* End updates.
|
|
||||||
*
|
|
||||||
* @param rangeController Sender.
|
|
||||||
* @param animated NO if all animations are disabled. YES otherwise.
|
|
||||||
* @param completion Completion block.
|
|
||||||
*/
|
|
||||||
- (void)rangeController:(ASRangeController * )rangeController endUpdatesAnimated:(BOOL)animated completion:(void (^ _Nullable)(BOOL))completion;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetch nodes at specific index paths.
|
* Fetch nodes at specific index paths.
|
||||||
@@ -98,7 +96,30 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
*
|
*
|
||||||
* @param indexPaths Index paths.
|
* @param indexPaths Index paths.
|
||||||
*/
|
*/
|
||||||
- (NSArray<ASCellNode *> *)rangeController:(ASRangeController *)rangeController nodesAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths;
|
- (NSArray *)rangeController:(ASRangeController *)rangeController nodesAtIndexPaths:(NSArray *)indexPaths;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delegate for ASRangeController.
|
||||||
|
*/
|
||||||
|
@protocol ASRangeControllerDelegate <NSObject>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Begin updates.
|
||||||
|
*
|
||||||
|
* @param rangeController Sender.
|
||||||
|
*/
|
||||||
|
- (void)didBeginUpdatesInRangeController:(ASRangeController *)rangeController;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* End updates.
|
||||||
|
*
|
||||||
|
* @param rangeController Sender.
|
||||||
|
* @param animated NO if all animations are disabled. YES otherwise.
|
||||||
|
* @param completion Completion block.
|
||||||
|
*/
|
||||||
|
- (void)rangeController:(ASRangeController * )rangeController didEndUpdatesAnimated:(BOOL)animated completion:(void (^)(BOOL))completion;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called for nodes insertion.
|
* Called for nodes insertion.
|
||||||
|
|||||||
@@ -31,22 +31,35 @@
|
|||||||
@implementation ASRangeController
|
@implementation ASRangeController
|
||||||
|
|
||||||
- (instancetype)init {
|
- (instancetype)init {
|
||||||
if (self = [super init]) {
|
self = [super init];
|
||||||
|
if (self != nil) {
|
||||||
_rangeIsValid = YES;
|
_rangeIsValid = YES;
|
||||||
_rangeTypeIndexPaths = [[NSMutableDictionary alloc] init];
|
_rangeTypeIndexPaths = [NSMutableDictionary dictionary];
|
||||||
|
|
||||||
_rangeTypeHandlers = @{
|
_rangeTypeHandlers = @{
|
||||||
@(ASLayoutRangeTypeRender): [[ASRangeHandlerRender alloc] init],
|
@(ASLayoutRangeTypeRender): [[ASRangeHandlerRender alloc] init],
|
||||||
@(ASLayoutRangeTypePreload): [[ASRangeHandlerPreload alloc] init],
|
@(ASLayoutRangeTypePreload): [[ASRangeHandlerPreload alloc] init],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma mark - Cell node view handling
|
||||||
|
|
||||||
#pragma mark - View manipulation
|
- (void)configureContentView:(UIView *)contentView forCellNode:(ASCellNode *)node
|
||||||
|
{
|
||||||
|
if (node.view.superview == contentView) {
|
||||||
|
// this content view is already correctly configured
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// clean the content view
|
||||||
|
for (UIView *view in contentView.subviews) {
|
||||||
|
[view removeFromSuperview];
|
||||||
|
}
|
||||||
|
|
||||||
|
[self moveCellNode:node toView:contentView];
|
||||||
|
}
|
||||||
|
|
||||||
- (void)moveCellNode:(ASCellNode *)node toView:(UIView *)view
|
- (void)moveCellNode:(ASCellNode *)node toView:(UIView *)view
|
||||||
{
|
{
|
||||||
@@ -62,8 +75,7 @@
|
|||||||
[view addSubview:node.view];
|
[view addSubview:node.view];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma mark - Core visible node range managment API
|
||||||
#pragma mark - API
|
|
||||||
|
|
||||||
- (void)visibleNodeIndexPathsDidChangeWithScrollDirection:(ASScrollDirection)scrollDirection
|
- (void)visibleNodeIndexPathsDidChangeWithScrollDirection:(ASScrollDirection)scrollDirection
|
||||||
{
|
{
|
||||||
@@ -76,27 +88,27 @@
|
|||||||
// coalesce these events -- handling them multiple times per runloop is noisy and expensive
|
// coalesce these events -- handling them multiple times per runloop is noisy and expensive
|
||||||
_queuedRangeUpdate = YES;
|
_queuedRangeUpdate = YES;
|
||||||
|
|
||||||
[self performSelector:@selector(updateVisibleNodeIndexPaths)
|
[self performSelector:@selector(_updateVisibleNodeIndexPaths)
|
||||||
withObject:nil
|
withObject:nil
|
||||||
afterDelay:0
|
afterDelay:0
|
||||||
inModes:@[ NSRunLoopCommonModes ]];
|
inModes:@[ NSRunLoopCommonModes ]];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)updateVisibleNodeIndexPaths
|
- (void)_updateVisibleNodeIndexPaths
|
||||||
{
|
{
|
||||||
if (!_queuedRangeUpdate) {
|
if (!_queuedRangeUpdate) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
NSArray *visibleNodePaths = [_delegate rangeControllerVisibleNodeIndexPaths:self];
|
NSArray *visibleNodePaths = [_dataSource visibleNodeIndexPathsForRangeController:self];
|
||||||
|
|
||||||
if ( visibleNodePaths.count == 0) { // if we don't have any visibleNodes currently (scrolled before or after content)...
|
if (visibleNodePaths.count == 0) { // if we don't have any visibleNodes currently (scrolled before or after content)...
|
||||||
_queuedRangeUpdate = NO;
|
_queuedRangeUpdate = NO;
|
||||||
return ; // don't do anything for this update, but leave _rangeIsValid to make sure we update it later
|
return ; // don't do anything for this update, but leave _rangeIsValid to make sure we update it later
|
||||||
}
|
}
|
||||||
|
|
||||||
NSSet *visibleNodePathsSet = [NSSet setWithArray:visibleNodePaths];
|
NSSet *visibleNodePathsSet = [NSSet setWithArray:visibleNodePaths];
|
||||||
CGSize viewportSize = [_delegate rangeControllerViewportSize:self];
|
CGSize viewportSize = [_dataSource viewportSizeForRangeController:self];
|
||||||
|
|
||||||
// the layout controller needs to know what the current visible indices are to calculate range offsets
|
// the layout controller needs to know what the current visible indices are to calculate range offsets
|
||||||
if ([_layoutController respondsToSelector:@selector(setVisibleNodeIndexPaths:)]) {
|
if ([_layoutController respondsToSelector:@selector(setVisibleNodeIndexPaths:)]) {
|
||||||
@@ -108,28 +120,30 @@
|
|||||||
id rangeKey = @(rangeType);
|
id rangeKey = @(rangeType);
|
||||||
|
|
||||||
// this delegate decide what happens when a node is added or removed from a range
|
// this delegate decide what happens when a node is added or removed from a range
|
||||||
id<ASRangeHandler> rangeDelegate = _rangeTypeHandlers[rangeKey];
|
id<ASRangeHandler> rangeHandler = _rangeTypeHandlers[rangeKey];
|
||||||
|
|
||||||
if (!_rangeIsValid || [_layoutController shouldUpdateForVisibleIndexPaths:visibleNodePaths viewportSize:viewportSize rangeType:rangeType]) {
|
if (!_rangeIsValid || [_layoutController shouldUpdateForVisibleIndexPaths:visibleNodePaths viewportSize:viewportSize rangeType:rangeType]) {
|
||||||
NSSet *indexPaths = [_layoutController indexPathsForScrolling:_scrollDirection viewportSize:viewportSize rangeType:rangeType];
|
NSSet *indexPaths = [_layoutController indexPathsForScrolling:_scrollDirection
|
||||||
|
viewportSize:viewportSize
|
||||||
|
rangeType:rangeType];
|
||||||
|
|
||||||
// Notify to remove indexpaths that are leftover that are not visible or included in the _layoutController calculated paths
|
// Notify to remove indexpaths that are leftover that are not visible or included in the _layoutController calculated paths
|
||||||
NSMutableSet *removedIndexPaths = _rangeIsValid ? [[_rangeTypeIndexPaths objectForKey:rangeKey] mutableCopy] : [NSMutableSet set];
|
NSMutableSet *removedIndexPaths = _rangeIsValid ? [_rangeTypeIndexPaths[rangeKey] mutableCopy] : [NSMutableSet set];
|
||||||
[removedIndexPaths minusSet:indexPaths];
|
[removedIndexPaths minusSet:indexPaths];
|
||||||
[removedIndexPaths minusSet:visibleNodePathsSet];
|
[removedIndexPaths minusSet:visibleNodePathsSet];
|
||||||
|
|
||||||
if (removedIndexPaths.count) {
|
if (removedIndexPaths.count) {
|
||||||
NSArray *removedNodes = [_delegate rangeController:self nodesAtIndexPaths:[removedIndexPaths allObjects]];
|
NSArray *removedNodes = [_dataSource rangeController:self nodesAtIndexPaths:[removedIndexPaths allObjects]];
|
||||||
[removedNodes enumerateObjectsUsingBlock:^(ASCellNode *node, NSUInteger idx, BOOL *stop) {
|
for (ASCellNode *node in removedNodes) {
|
||||||
// since this class usually manages large or infinite data sets, the working range
|
// since this class usually manages large or infinite data sets, the working range
|
||||||
// directly bounds memory usage by requiring redrawing any content that falls outside the range.
|
// directly bounds memory usage by requiring redrawing any content that falls outside the range.
|
||||||
[rangeDelegate node:node exitedRangeOfType:rangeType];
|
[rangeHandler node:node exitedRangeOfType:rangeType];
|
||||||
}];
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notify to add indexpaths that are not currently in _rangeTypeIndexPaths
|
// Notify to add index paths that are not currently in _rangeTypeIndexPaths
|
||||||
NSMutableSet *addedIndexPaths = [indexPaths mutableCopy];
|
NSMutableSet *addedIndexPaths = [indexPaths mutableCopy];
|
||||||
[addedIndexPaths minusSet:[_rangeTypeIndexPaths objectForKey:rangeKey]];
|
[addedIndexPaths minusSet:_rangeTypeIndexPaths[rangeKey]];
|
||||||
|
|
||||||
// The preload range (for example) should include nodes that are visible
|
// The preload range (for example) should include nodes that are visible
|
||||||
// TODO: remove this once we have removed the dependency on Core Animation's -display
|
// TODO: remove this once we have removed the dependency on Core Animation's -display
|
||||||
@@ -138,14 +152,14 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (addedIndexPaths.count) {
|
if (addedIndexPaths.count) {
|
||||||
NSArray *addedNodes = [_delegate rangeController:self nodesAtIndexPaths:[addedIndexPaths allObjects]];
|
NSArray *addedNodes = [_dataSource rangeController:self nodesAtIndexPaths:[addedIndexPaths allObjects]];
|
||||||
[addedNodes enumerateObjectsUsingBlock:^(ASCellNode *node, NSUInteger idx, BOOL *stop) {
|
for (ASCellNode *node in addedNodes) {
|
||||||
[rangeDelegate node:node enteredRangeOfType:rangeType];
|
[rangeHandler node:node enteredRangeOfType:rangeType];
|
||||||
}];
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// set the range indexpaths so that we can remove/add on the next update pass
|
// set the range indexpaths so that we can remove/add on the next update pass
|
||||||
[_rangeTypeIndexPaths setObject:indexPaths forKey:rangeKey];
|
_rangeTypeIndexPaths[rangeKey] = indexPaths;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,33 +172,17 @@
|
|||||||
return rangeType == ASLayoutRangeTypeRender;
|
return rangeType == ASLayoutRangeTypeRender;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)configureContentView:(UIView *)contentView forCellNode:(ASCellNode *)node
|
|
||||||
{
|
|
||||||
if (node.view.superview == contentView) {
|
|
||||||
// this content view is already correctly configured
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// clean the content view
|
|
||||||
for (UIView *view in contentView.subviews) {
|
|
||||||
[view removeFromSuperview];
|
|
||||||
}
|
|
||||||
|
|
||||||
[self moveCellNode:node toView:contentView];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#pragma mark - ASDataControllerDelegete
|
#pragma mark - ASDataControllerDelegete
|
||||||
|
|
||||||
- (void)dataControllerBeginUpdates:(ASDataController *)dataController {
|
- (void)dataControllerBeginUpdates:(ASDataController *)dataController {
|
||||||
ASPerformBlockOnMainThread(^{
|
ASPerformBlockOnMainThread(^{
|
||||||
[_delegate rangeControllerBeginUpdates:self];
|
[_delegate didBeginUpdatesInRangeController:self];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)dataController:(ASDataController *)dataController endUpdatesAnimated:(BOOL)animated completion:(void (^)(BOOL))completion {
|
- (void)dataController:(ASDataController *)dataController endUpdatesAnimated:(BOOL)animated completion:(void (^)(BOOL))completion {
|
||||||
ASPerformBlockOnMainThread(^{
|
ASPerformBlockOnMainThread(^{
|
||||||
[_delegate rangeController:self endUpdatesAnimated:animated completion:completion];
|
[_delegate rangeController:self didEndUpdatesAnimated:animated completion:completion];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -204,7 +204,6 @@
|
|||||||
3EEA4EE01BECC4A1008A7F35 /* Sources */,
|
3EEA4EE01BECC4A1008A7F35 /* Sources */,
|
||||||
3EEA4EE11BECC4A1008A7F35 /* Frameworks */,
|
3EEA4EE11BECC4A1008A7F35 /* Frameworks */,
|
||||||
3EEA4EE21BECC4A1008A7F35 /* Resources */,
|
3EEA4EE21BECC4A1008A7F35 /* Resources */,
|
||||||
F8CD1BCEB86661EF98DB1C0C /* Embed Pods Frameworks */,
|
|
||||||
21F2C1D9B53F9468EAF1653F /* Copy Pods Resources */,
|
21F2C1D9B53F9468EAF1653F /* Copy Pods Resources */,
|
||||||
);
|
);
|
||||||
buildRules = (
|
buildRules = (
|
||||||
@@ -311,21 +310,6 @@
|
|||||||
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n";
|
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n";
|
||||||
showEnvVarsInLog = 0;
|
showEnvVarsInLog = 0;
|
||||||
};
|
};
|
||||||
F8CD1BCEB86661EF98DB1C0C /* Embed Pods Frameworks */ = {
|
|
||||||
isa = PBXShellScriptBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
);
|
|
||||||
inputPaths = (
|
|
||||||
);
|
|
||||||
name = "Embed Pods Frameworks";
|
|
||||||
outputPaths = (
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
shellPath = /bin/sh;
|
|
||||||
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-frameworks.sh\"\n";
|
|
||||||
showEnvVarsInLog = 0;
|
|
||||||
};
|
|
||||||
/* End PBXShellScriptBuildPhase section */
|
/* End PBXShellScriptBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXSourcesBuildPhase section */
|
/* Begin PBXSourcesBuildPhase section */
|
||||||
|
|||||||
Reference in New Issue
Block a user