mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-24 07:05:35 +00:00
Introduce ASCollectionLayout and friends (#3130)
* Introduce ASCollectionViewLayout - `ASCollectionViewLayout` is an async `UICollectionViewLayout` that encapsulates its layout calculation logic into a separate thread-safe object which can be used ahead of time and/or on multiple threads. - `ASDataController` now can prepare for a new layout resulted from a change set before `ASCollectionView` even knows about it. By the time the change set it ready to be consumed by `ASCollectionView`, its new layout is also ready. - New `ASCollectionViewLayoutCalculating` protocol that is simple and generic enough that many types of calculators can be built on top. `ASCollectionViewLayoutSpecCalculator` conforms to `ASCollectionViewLayoutCalculating` protocol and can be backed by any layout spec (e.g `ASStackLayoutSpec`, `PIMasonryLayoutSpec`, etc). We can even build a `ASCollectionViewLayoutYogaCalculator` that uses Yoga internally. - A built-in `ASCollectionViewFlowLayoutCalculator` that is a subclass of `ASCollectionViewLayoutSpecCalculator` and uses a multi-threaded multi-line `ASStackLayoutSpec` internally. The result is a performant and thread-safe flow layout calculator. - Finally, `ASCollectionViewLayout` can be subclassed to handle a specific type of calculator with optimizations implemented based on the knowledge of such calculator. For example, `ASCollectionViewFlowLayout` can have a highly optimized implementation of `-layoutAttributesForElementsInRect:`. Protocolize layout calculator providing and consuming Add flex wrap documentation Add a `multithreaded` flag to ASStackLayoutSpec that forces it to dispatch even if it's off main - Update ASCollectionViewFlowLayoutSpecCalculator to use that flag. Minor change in ASCollectionViewLayout Implement Mosaic layout calculator Minor change Fix project file Rename and fix project file Skip fetching constrained size only if a layout calculator is available Update examples/ASCollectionView Remove unnecessary change in ASTableView Address comments Rename collection view calculator protocols Minor changes after rebasing with master Add ASLegacyCollectionLayoutCalculator for backward compatibility Remove ASCollectionLayoutSpecCalculator Remove ASLegacyCollectionLayoutCalculator Introduce ASCollectionLayout - A wrapper object that contains content size and an element to rect table. - Collection layout calculators to return this new object instead of an ASLayout. Before adding a content cache Finishing hooking up ASCollectionLayoutDataSource to ASCollectionNode Stash Finish ASCollectionLayout Rough impl of ASCollectionFlowLayout Revert changes in CustomCollectionView example Move ASRectTable back to Private * Rename ASCollectionContentAttributes to ASCollectionLayoutState * Address other comments * Introduce ASCollectionLayoutDelegate and make ASCollectionLayout private * Address comments * API tweaks: - Replace `-layoutContextWithElementMap:` in ASCollectionLayoutDelegate with `-additionalInfoForLayoutWithElements:`. The returned object is then stored in ASCollectionLayoutContext for later lookups. - ASCollectionLayoutContext has no public initializer. - ASDataControllerLayoutDelegate no longer requires a context of type ASCollectionLayoutContext but simply an `id`. This helps decouple ASDataController and ASCollectionLayout. - Rename `elementMap` to `elements`. - Rename `visibleMap` to `visibleElements`. - Other minor changes. * Rename ASCGSizeHash to ASHashFromCGSize * Make sure to call super in -[ASCollectionLayout prepareLayout] * Update example/ASCollectionView to use ASCollectionFlowLayoutDelegate * Remove unnecessary change
This commit is contained in:
@@ -11,10 +11,12 @@
|
||||
//
|
||||
|
||||
#import <AsyncDisplayKit/ASCollectionNode.h>
|
||||
#import <AsyncDisplayKit/ASCollectionNode+Beta.h>
|
||||
|
||||
#import <AsyncDisplayKit/ASCollectionElement.h>
|
||||
#import <AsyncDisplayKit/ASElementMap.h>
|
||||
#import <AsyncDisplayKit/ASCollectionInternal.h>
|
||||
#import <AsyncDisplayKit/ASCollectionLayout.h>
|
||||
#import <AsyncDisplayKit/ASCollectionViewLayoutFacilitatorProtocol.h>
|
||||
#import <AsyncDisplayKit/ASDisplayNode+Beta.h>
|
||||
#import <AsyncDisplayKit/ASDisplayNode+Subclasses.h>
|
||||
@@ -33,6 +35,7 @@
|
||||
@interface _ASCollectionPendingState : NSObject
|
||||
@property (weak, nonatomic) id <ASCollectionDelegate> delegate;
|
||||
@property (weak, nonatomic) id <ASCollectionDataSource> dataSource;
|
||||
@property (strong, nonatomic) UICollectionViewLayout *collectionViewLayout;
|
||||
@property (nonatomic, assign) ASLayoutRangeMode rangeMode;
|
||||
@property (nonatomic, assign) BOOL allowsSelection; // default is YES
|
||||
@property (nonatomic, assign) BOOL allowsMultipleSelection; // default is NO
|
||||
@@ -133,13 +136,21 @@
|
||||
return [self initWithFrame:frame collectionViewLayout:layout layoutFacilitator:nil];
|
||||
}
|
||||
|
||||
- (instancetype)initWithLayoutDelegate:(id<ASCollectionLayoutDelegate>)layoutDelegate layoutFacilitator:(id<ASCollectionViewLayoutFacilitatorProtocol>)layoutFacilitator
|
||||
{
|
||||
return [self initWithFrame:CGRectZero collectionViewLayout:[[ASCollectionLayout alloc] initWithLayoutDelegate:layoutDelegate] layoutFacilitator:layoutFacilitator];
|
||||
}
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout layoutFacilitator:(id<ASCollectionViewLayoutFacilitatorProtocol>)layoutFacilitator
|
||||
{
|
||||
if (self = [super init]) {
|
||||
// Must call the setter here to make sure pendingState is created and the layout is configured.
|
||||
[self setCollectionViewLayout:layout];
|
||||
|
||||
__weak __typeof__(self) weakSelf = self;
|
||||
[self setViewBlock:^{
|
||||
__typeof__(self) strongSelf = weakSelf;
|
||||
return [[[strongSelf collectionViewClass] alloc] _initWithFrame:frame collectionViewLayout:layout layoutFacilitator:layoutFacilitator eventLog:ASDisplayNodeGetEventLog(strongSelf)];
|
||||
return [[[strongSelf collectionViewClass] alloc] _initWithFrame:frame collectionViewLayout:strongSelf->_pendingState.collectionViewLayout layoutFacilitator:layoutFacilitator eventLog:ASDisplayNodeGetEventLog(strongSelf)];
|
||||
}];
|
||||
}
|
||||
return self;
|
||||
@@ -162,10 +173,12 @@
|
||||
view.inverted = pendingState.inverted;
|
||||
view.allowsSelection = pendingState.allowsSelection;
|
||||
view.allowsMultipleSelection = pendingState.allowsMultipleSelection;
|
||||
|
||||
|
||||
if (pendingState.rangeMode != ASLayoutRangeModeUnspecified) {
|
||||
[view.rangeController updateCurrentRangeWithMode:pendingState.rangeMode];
|
||||
}
|
||||
|
||||
// Don't need to set collectionViewLayout to the view as the layout was already used to init the view in view block.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -340,6 +353,42 @@
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setCollectionViewLayout:(UICollectionViewLayout *)layout
|
||||
{
|
||||
if ([self pendingState]) {
|
||||
[self _configureCollectionViewLayout:layout];
|
||||
_pendingState.collectionViewLayout = layout;
|
||||
} else {
|
||||
[self _configureCollectionViewLayout:layout];
|
||||
self.view.collectionViewLayout = layout;
|
||||
}
|
||||
}
|
||||
|
||||
- (UICollectionViewLayout *)collectionViewLayout
|
||||
{
|
||||
if ([self pendingState]) {
|
||||
return _pendingState.collectionViewLayout;
|
||||
} else {
|
||||
return self.view.collectionViewLayout;
|
||||
}
|
||||
}
|
||||
|
||||
- (ASElementMap *)visibleElements
|
||||
{
|
||||
ASDisplayNodeAssertMainThread();
|
||||
// TODO Own the data controller when view is not yet loaded
|
||||
return self.dataController.visibleMap;
|
||||
}
|
||||
|
||||
- (id<ASCollectionLayoutDelegate>)layoutDelegate
|
||||
{
|
||||
UICollectionViewLayout *layout = self.collectionViewLayout;
|
||||
if ([layout isKindOfClass:[ASCollectionLayout class]]) {
|
||||
return ((ASCollectionLayout *)layout).layoutDelegate;
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
#pragma mark - Range Tuning
|
||||
|
||||
- (ASRangeTuningParameters)tuningParametersForRangeType:(ASLayoutRangeType)rangeType
|
||||
@@ -662,4 +711,14 @@ ASLayoutElementCollectionTableSetTraitCollection(_environmentStateLock)
|
||||
return result;
|
||||
}
|
||||
|
||||
#pragma mark - Private methods
|
||||
|
||||
- (void)_configureCollectionViewLayout:(UICollectionViewLayout *)layout
|
||||
{
|
||||
if ([layout isKindOfClass:[ASCollectionLayout class]]) {
|
||||
ASCollectionLayout *collectionLayout = (ASCollectionLayout *)layout;
|
||||
collectionLayout.collectionNode = self;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Reference in New Issue
Block a user