Make Cell Node Properties Atomic (#74)

* Make ASCellNode indexPath and supplementaryElementKind atomic

* Update the change log

* Fix licenses

* Be explicit with atomic

* Rename the protocol

* And the file
This commit is contained in:
Adlai Holler 2017-05-02 14:09:12 -07:00 committed by GitHub
parent 471f02daa7
commit a7656766f9
20 changed files with 131 additions and 142 deletions

View File

@ -368,6 +368,7 @@
CCA282D01E9EBF6C0037E8B7 /* ASTipsWindow.h in Headers */ = {isa = PBXBuildFile; fileRef = CCA282CE1E9EBF6C0037E8B7 /* ASTipsWindow.h */; }; CCA282D01E9EBF6C0037E8B7 /* ASTipsWindow.h in Headers */ = {isa = PBXBuildFile; fileRef = CCA282CE1E9EBF6C0037E8B7 /* ASTipsWindow.h */; };
CCA282D11E9EBF6C0037E8B7 /* ASTipsWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = CCA282CF1E9EBF6C0037E8B7 /* ASTipsWindow.m */; }; CCA282D11E9EBF6C0037E8B7 /* ASTipsWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = CCA282CF1E9EBF6C0037E8B7 /* ASTipsWindow.m */; };
CCB2F34D1D63CCC6004E6DE9 /* ASDisplayNodeSnapshotTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CCB2F34C1D63CCC6004E6DE9 /* ASDisplayNodeSnapshotTests.m */; }; CCB2F34D1D63CCC6004E6DE9 /* ASDisplayNodeSnapshotTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CCB2F34C1D63CCC6004E6DE9 /* ASDisplayNodeSnapshotTests.m */; };
CCBBBF5D1EB161760069AA91 /* ASRangeManagingNode.h in Headers */ = {isa = PBXBuildFile; fileRef = CCBBBF5C1EB161760069AA91 /* ASRangeManagingNode.h */; settings = {ATTRIBUTES = (Public, ); }; };
CCF18FF41D2575E300DF5895 /* NSIndexSet+ASHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = CC4981BA1D1C7F65004E13CC /* NSIndexSet+ASHelpers.h */; settings = {ATTRIBUTES = (Private, ); }; }; CCF18FF41D2575E300DF5895 /* NSIndexSet+ASHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = CC4981BA1D1C7F65004E13CC /* NSIndexSet+ASHelpers.h */; settings = {ATTRIBUTES = (Private, ); }; };
DB55C2671C641AE4004EDCF5 /* ASContextTransitioning.h in Headers */ = {isa = PBXBuildFile; fileRef = DB55C2651C641AE4004EDCF5 /* ASContextTransitioning.h */; settings = {ATTRIBUTES = (Public, ); }; }; DB55C2671C641AE4004EDCF5 /* ASContextTransitioning.h in Headers */ = {isa = PBXBuildFile; fileRef = DB55C2651C641AE4004EDCF5 /* ASContextTransitioning.h */; settings = {ATTRIBUTES = (Public, ); }; };
DB7121BCD50849C498C886FB /* libPods-AsyncDisplayKitTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = EFA731F0396842FF8AB635EE /* libPods-AsyncDisplayKitTests.a */; }; DB7121BCD50849C498C886FB /* libPods-AsyncDisplayKitTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = EFA731F0396842FF8AB635EE /* libPods-AsyncDisplayKitTests.a */; };
@ -798,6 +799,7 @@
CCA282CE1E9EBF6C0037E8B7 /* ASTipsWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASTipsWindow.h; sourceTree = "<group>"; }; CCA282CE1E9EBF6C0037E8B7 /* ASTipsWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASTipsWindow.h; sourceTree = "<group>"; };
CCA282CF1E9EBF6C0037E8B7 /* ASTipsWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASTipsWindow.m; sourceTree = "<group>"; }; CCA282CF1E9EBF6C0037E8B7 /* ASTipsWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASTipsWindow.m; sourceTree = "<group>"; };
CCB2F34C1D63CCC6004E6DE9 /* ASDisplayNodeSnapshotTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASDisplayNodeSnapshotTests.m; sourceTree = "<group>"; }; CCB2F34C1D63CCC6004E6DE9 /* ASDisplayNodeSnapshotTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASDisplayNodeSnapshotTests.m; sourceTree = "<group>"; };
CCBBBF5C1EB161760069AA91 /* ASRangeManagingNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASRangeManagingNode.h; sourceTree = "<group>"; };
CCBD05DE1E4147B000D18509 /* ASIGListAdapterBasedDataSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASIGListAdapterBasedDataSource.m; sourceTree = "<group>"; }; CCBD05DE1E4147B000D18509 /* ASIGListAdapterBasedDataSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASIGListAdapterBasedDataSource.m; sourceTree = "<group>"; };
CCBD05DF1E4147B000D18509 /* ASIGListAdapterBasedDataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASIGListAdapterBasedDataSource.h; sourceTree = "<group>"; }; CCBD05DF1E4147B000D18509 /* ASIGListAdapterBasedDataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASIGListAdapterBasedDataSource.h; sourceTree = "<group>"; };
CCE04B1E1E313EA7006AEBBB /* ASSectionController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASSectionController.h; sourceTree = "<group>"; }; CCE04B1E1E313EA7006AEBBB /* ASSectionController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASSectionController.h; sourceTree = "<group>"; };
@ -1002,6 +1004,7 @@
25E327551C16819500A2170C /* ASPagerNode.m */, 25E327551C16819500A2170C /* ASPagerNode.m */,
A2763D771CBDD57D00A9ADBD /* ASPINRemoteImageDownloader.h */, A2763D771CBDD57D00A9ADBD /* ASPINRemoteImageDownloader.h */,
A2763D781CBDD57D00A9ADBD /* ASPINRemoteImageDownloader.m */, A2763D781CBDD57D00A9ADBD /* ASPINRemoteImageDownloader.m */,
CCBBBF5C1EB161760069AA91 /* ASRangeManagingNode.h */,
ACE87A2B1D73696800D7FF06 /* ASSectionContext.h */, ACE87A2B1D73696800D7FF06 /* ASSectionContext.h */,
D785F6601A74327E00291744 /* ASScrollNode.h */, D785F6601A74327E00291744 /* ASScrollNode.h */,
D785F6611A74327E00291744 /* ASScrollNode.mm */, D785F6611A74327E00291744 /* ASScrollNode.mm */,
@ -1533,6 +1536,7 @@
509E68611B3AEDA0009B9150 /* ASAbstractLayoutController.h in Headers */, 509E68611B3AEDA0009B9150 /* ASAbstractLayoutController.h in Headers */,
CCA282B81E9EA8E40037E8B7 /* AsyncDisplayKit+Tips.h in Headers */, CCA282B81E9EA8E40037E8B7 /* AsyncDisplayKit+Tips.h in Headers */,
B35062571B010F070018CF92 /* ASAssert.h in Headers */, B35062571B010F070018CF92 /* ASAssert.h in Headers */,
CCBBBF5D1EB161760069AA91 /* ASRangeManagingNode.h in Headers */,
B35062581B010F070018CF92 /* ASAvailability.h in Headers */, B35062581B010F070018CF92 /* ASAvailability.h in Headers */,
DE84918D1C8FFF2B003D89E9 /* ASRunLoopQueue.h in Headers */, DE84918D1C8FFF2B003D89E9 /* ASRunLoopQueue.h in Headers */,
CC0F88621E4281E200576FED /* ASSectionController.h in Headers */, CC0F88621E4281E200576FED /* ASSectionController.h in Headers */,

View File

@ -5,6 +5,7 @@
- Fix `__has_include` check in ASLog.h [Philipp Smorygo](Philipp.Smorygo@jetbrains.com) - Fix `__has_include` check in ASLog.h [Philipp Smorygo](Philipp.Smorygo@jetbrains.com)
- Fix potential deadlock in ASControlNode [Garrett Moon](https://github.com/garrettmoon) - Fix potential deadlock in ASControlNode [Garrett Moon](https://github.com/garrettmoon)
- [Yoga Beta] Improvements to the experimental support for Yoga layout [Scott Goodson](appleguy) - [Yoga Beta] Improvements to the experimental support for Yoga layout [Scott Goodson](appleguy)
- Make cell node `indexPath` and `supplementaryElementKind` atomic so you can read from any thread. (Adlai-Holler)[https://github.com/Adlai-Holler] (#49)[https://github.com/TextureGroup/Texture/pull/74]
- Update the rasterization API and un-deprecate it. [Adlai Holler](https://github.com/Adlai-Holler)[#82](https://github.com/TextureGroup/Texture/pull/49) - Update the rasterization API and un-deprecate it. [Adlai Holler](https://github.com/Adlai-Holler)[#82](https://github.com/TextureGroup/Texture/pull/49)
- Simplified & optimized hashing code. [Adlai Holler](https://github.com/Adlai-Holler) [#86](https://github.com/TextureGroup/Texture/pull/86) - Simplified & optimized hashing code. [Adlai Holler](https://github.com/Adlai-Holler) [#86](https://github.com/TextureGroup/Texture/pull/86)
- Improve the performance & safety of ASDisplayNode subnodes. [Adlai Holler](https://github.com/Adlai-Holler) [#223](https://github.com/TextureGroup/Texture/pull/223) - Improve the performance & safety of ASDisplayNode subnodes. [Adlai Holler](https://github.com/Adlai-Holler) [#223](https://github.com/TextureGroup/Texture/pull/223)

View File

@ -20,6 +20,7 @@
NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_BEGIN
@class ASCellNode, ASTextNode; @class ASCellNode, ASTextNode;
@protocol ASRangeManagingNode;
typedef NSUInteger ASCellNodeAnimation; typedef NSUInteger ASCellNodeAnimation;
@ -87,7 +88,7 @@ typedef NS_ENUM(NSUInteger, ASCellNodeVisibilityEvent) {
* @return The supplementary element kind, or @c nil if this node does not represent a supplementary element. * @return The supplementary element kind, or @c nil if this node does not represent a supplementary element.
*/ */
//TODO change this to be a generic "kind" or "elementKind" that exposes `nil` for row kind //TODO change this to be a generic "kind" or "elementKind" that exposes `nil` for row kind
@property (nonatomic, copy, readonly, nullable) NSString *supplementaryElementKind; @property (atomic, copy, readonly, nullable) NSString *supplementaryElementKind;
/* /*
* The layout attributes currently assigned to this node, if any. * The layout attributes currently assigned to this node, if any.
@ -113,10 +114,8 @@ typedef NS_ENUM(NSUInteger, ASCellNodeVisibilityEvent) {
/** /**
* The current index path of this cell node, or @c nil if this node is * The current index path of this cell node, or @c nil if this node is
* not a valid item inside a table node or collection node. * not a valid item inside a table node or collection node.
*
* @note This property must be accessed on the main thread.
*/ */
@property (nonatomic, readonly, nullable) NSIndexPath *indexPath; @property (atomic, readonly, nullable) NSIndexPath *indexPath;
/** /**
* The backing view controller, or @c nil if the node wasn't initialized with backing view controller * The backing view controller, or @c nil if the node wasn't initialized with backing view controller
@ -126,10 +125,9 @@ typedef NS_ENUM(NSUInteger, ASCellNodeVisibilityEvent) {
/** /**
* The owning node (ASCollectionNode/ASTableNode) of this cell node, or @c nil if this node is * The table- or collection-node that this cell is a member of, if any.
* not a valid item inside a table node or collection node or if those nodes are nil.
*/ */
@property (weak, nonatomic, readonly, nullable) ASDisplayNode *owningNode; @property (atomic, weak, readonly, nullable) id<ASRangeManagingNode> owningNode;
/* /*
* ASCellNode must forward touch events in order for UITableView and UICollectionView tap handling to work. Overriding * ASCellNode must forward touch events in order for UITableView and UICollectionView tap handling to work. Overriding

View File

@ -44,12 +44,6 @@
ASDisplayNode *_viewControllerNode; ASDisplayNode *_viewControllerNode;
UIViewController *_viewController; UIViewController *_viewController;
BOOL _suspendInteractionDelegate; BOOL _suspendInteractionDelegate;
struct {
unsigned int isTableNode:1;
unsigned int isCollectionNode:1;
} _owningNodeType;
} }
@end @end
@ -165,19 +159,6 @@
} }
} }
- (void)setOwningNode:(ASDisplayNode *)owningNode
{
_owningNode = owningNode;
memset(&_owningNodeType, 0, sizeof(_owningNodeType));
if ([owningNode isKindOfClass:[ASTableNode class]]) {
_owningNodeType.isTableNode = 1;
} else if ([owningNode isKindOfClass:[ASCollectionNode class]]) {
_owningNodeType.isCollectionNode = 1;
}
}
- (void)__setSelectedFromUIKit:(BOOL)selected; - (void)__setSelectedFromUIKit:(BOOL)selected;
{ {
if (selected != _selected) { if (selected != _selected) {
@ -198,15 +179,7 @@
- (NSIndexPath *)indexPath - (NSIndexPath *)indexPath
{ {
ASDisplayNodeAssertMainThread(); return [self.owningNode indexPathForNode:self];
if (_owningNodeType.isTableNode) {
return [(ASTableNode *)self.owningNode indexPathForNode:self];
} else if (_owningNodeType.isCollectionNode) {
return [(ASCollectionNode *)self.owningNode indexPathForNode:self];
}
return nil;
} }
- (UIViewController *)viewController - (UIViewController *)viewController

View File

@ -20,6 +20,7 @@
#import <AsyncDisplayKit/ASRangeControllerUpdateRangeProtocol+Beta.h> #import <AsyncDisplayKit/ASRangeControllerUpdateRangeProtocol+Beta.h>
#import <AsyncDisplayKit/ASCollectionView.h> #import <AsyncDisplayKit/ASCollectionView.h>
#import <AsyncDisplayKit/ASBlockTypes.h> #import <AsyncDisplayKit/ASBlockTypes.h>
#import <AsyncDisplayKit/ASRangeManagingNode.h>
@protocol ASCollectionViewLayoutFacilitatorProtocol; @protocol ASCollectionViewLayoutFacilitatorProtocol;
@protocol ASCollectionDelegate; @protocol ASCollectionDelegate;
@ -32,7 +33,7 @@ NS_ASSUME_NONNULL_BEGIN
* ASCollectionNode is a node based class that wraps an ASCollectionView. It can be used * ASCollectionNode is a node based class that wraps an ASCollectionView. It can be used
* as a subnode of another node, and provide room for many (great) features and improvements later on. * as a subnode of another node, and provide room for many (great) features and improvements later on.
*/ */
@interface ASCollectionNode : ASDisplayNode <ASRangeControllerUpdateRangeProtocol> @interface ASCollectionNode : ASDisplayNode <ASRangeControllerUpdateRangeProtocol, ASRangeManagingNode>
- (instancetype)init NS_UNAVAILABLE; - (instancetype)init NS_UNAVAILABLE;

View File

@ -155,7 +155,7 @@
__weak __typeof__(self) weakSelf = self; __weak __typeof__(self) weakSelf = self;
[self setViewBlock:^{ [self setViewBlock:^{
__typeof__(self) strongSelf = weakSelf; __typeof__(self) strongSelf = weakSelf;
return [[[strongSelf collectionViewClass] alloc] _initWithFrame:frame collectionViewLayout:strongSelf->_pendingState.collectionViewLayout layoutFacilitator:layoutFacilitator eventLog:ASDisplayNodeGetEventLog(strongSelf)]; return [[[strongSelf collectionViewClass] alloc] _initWithFrame:frame collectionViewLayout:strongSelf->_pendingState.collectionViewLayout layoutFacilitator:layoutFacilitator owningNode:strongSelf eventLog:ASDisplayNodeGetEventLog(strongSelf)];
}]; }];
} }
return self; return self;

View File

@ -80,7 +80,7 @@ static NSString * const kReuseIdentifier = @"_ASCollectionReuseIdentifier";
#pragma mark - #pragma mark -
#pragma mark ASCollectionView. #pragma mark ASCollectionView.
@interface ASCollectionView () <ASRangeControllerDataSource, ASRangeControllerDelegate, ASDataControllerSource, ASCellNodeInteractionDelegate, ASDelegateProxyInterceptor, ASBatchFetchingScrollView, ASDataControllerEnvironmentDelegate, ASCALayerExtendedDelegate, UICollectionViewDelegateFlowLayout> { @interface ASCollectionView () <ASRangeControllerDataSource, ASRangeControllerDelegate, ASDataControllerSource, ASCellNodeInteractionDelegate, ASDelegateProxyInterceptor, ASBatchFetchingScrollView, ASCALayerExtendedDelegate, UICollectionViewDelegateFlowLayout> {
ASCollectionViewProxy *_proxyDataSource; ASCollectionViewProxy *_proxyDataSource;
ASCollectionViewProxy *_proxyDelegate; ASCollectionViewProxy *_proxyDelegate;
@ -250,10 +250,10 @@ static NSString * const kReuseIdentifier = @"_ASCollectionReuseIdentifier";
- (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout - (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout
{ {
return [self _initWithFrame:frame collectionViewLayout:layout layoutFacilitator:nil eventLog:nil]; return [self _initWithFrame:frame collectionViewLayout:layout layoutFacilitator:nil owningNode:nil eventLog:nil];
} }
- (instancetype)_initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout layoutFacilitator:(id<ASCollectionViewLayoutFacilitatorProtocol>)layoutFacilitator eventLog:(ASEventLog *)eventLog - (instancetype)_initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout layoutFacilitator:(id<ASCollectionViewLayoutFacilitatorProtocol>)layoutFacilitator owningNode:(ASCollectionNode *)owningNode eventLog:(ASEventLog *)eventLog
{ {
if (!(self = [super initWithFrame:frame collectionViewLayout:layout])) if (!(self = [super initWithFrame:frame collectionViewLayout:layout]))
return nil; return nil;
@ -273,9 +273,8 @@ static NSString * const kReuseIdentifier = @"_ASCollectionReuseIdentifier";
_rangeController.delegate = self; _rangeController.delegate = self;
_rangeController.layoutController = _layoutController; _rangeController.layoutController = _layoutController;
_dataController = [[ASDataController alloc] initWithDataSource:self eventLog:eventLog]; _dataController = [[ASDataController alloc] initWithDataSource:self node:owningNode eventLog:eventLog];
_dataController.delegate = _rangeController; _dataController.delegate = _rangeController;
_dataController.environmentDelegate = self;
_batchContext = [[ASBatchContext alloc] init]; _batchContext = [[ASBatchContext alloc] init];
@ -1649,11 +1648,6 @@ static NSString * const kReuseIdentifier = @"_ASCollectionReuseIdentifier";
} }
- (id<ASTraitEnvironment>)dataControllerEnvironment
{
return self.collectionNode;
}
#pragma mark - ASDataControllerSource optional methods #pragma mark - ASDataControllerSource optional methods
- (ASCellNodeBlock)dataController:(ASDataController *)dataController supplementaryNodeBlockOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath - (ASCellNodeBlock)dataController:(ASDataController *)dataController supplementaryNodeBlockOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath

View File

@ -0,0 +1,35 @@
//
// ASRangeManagingNode.h
// Texture
//
// Copyright (c) 2017-present, Pinterest, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
#import <Foundation/Foundation.h>
#import <AsyncDisplayKit/ASTraitCollection.h>
@class ASCellNode;
NS_ASSUME_NONNULL_BEGIN
/**
* Basically ASTableNode or ASCollectionNode.
*/
@protocol ASRangeManagingNode <NSObject, ASTraitEnvironment>
/**
* Retrieve the index path for the given node, if it's a member of this container.
*
* @param node The node.
* @return The index path, or nil if the node is not part of this container.
*/
- (nullable NSIndexPath *)indexPathForNode:(ASCellNode *)node;
@end
NS_ASSUME_NONNULL_END

View File

@ -19,7 +19,7 @@
#import <AsyncDisplayKit/ASDisplayNode.h> #import <AsyncDisplayKit/ASDisplayNode.h>
#import <AsyncDisplayKit/ASRangeControllerUpdateRangeProtocol+Beta.h> #import <AsyncDisplayKit/ASRangeControllerUpdateRangeProtocol+Beta.h>
#import <AsyncDisplayKit/ASTableView.h> #import <AsyncDisplayKit/ASTableView.h>
#import <AsyncDisplayKit/ASRangeManagingNode.h>
NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_BEGIN
@ -31,7 +31,7 @@ NS_ASSUME_NONNULL_BEGIN
* ASTableNode is a node based class that wraps an ASTableView. It can be used * ASTableNode is a node based class that wraps an ASTableView. It can be used
* as a subnode of another node, and provide room for many (great) features and improvements later on. * as a subnode of another node, and provide room for many (great) features and improvements later on.
*/ */
@interface ASTableNode : ASDisplayNode <ASRangeControllerUpdateRangeProtocol> @interface ASTableNode : ASDisplayNode <ASRangeControllerUpdateRangeProtocol, ASRangeManagingNode>
- (instancetype)init; // UITableViewStylePlain - (instancetype)init; // UITableViewStylePlain
- (instancetype)initWithStyle:(UITableViewStyle)style NS_DESIGNATED_INITIALIZER; - (instancetype)initWithStyle:(UITableViewStyle)style NS_DESIGNATED_INITIALIZER;

View File

@ -80,7 +80,7 @@
[self setViewBlock:^{ [self setViewBlock:^{
// Variable will be unused if event logging is off. // Variable will be unused if event logging is off.
__unused __typeof__(self) strongSelf = weakSelf; __unused __typeof__(self) strongSelf = weakSelf;
return [[ASTableView alloc] _initWithFrame:CGRectZero style:style dataControllerClass:nil eventLog:ASDisplayNodeGetEventLog(strongSelf)]; return [[ASTableView alloc] _initWithFrame:CGRectZero style:style dataControllerClass:nil owningNode:strongSelf eventLog:ASDisplayNodeGetEventLog(strongSelf)];
}]; }];
} }
return self; return self;

View File

@ -147,7 +147,7 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
#pragma mark - #pragma mark -
#pragma mark ASTableView #pragma mark ASTableView
@interface ASTableView () <ASRangeControllerDataSource, ASRangeControllerDelegate, ASDataControllerSource, _ASTableViewCellDelegate, ASCellNodeInteractionDelegate, ASDelegateProxyInterceptor, ASBatchFetchingScrollView, ASDataControllerEnvironmentDelegate> @interface ASTableView () <ASRangeControllerDataSource, ASRangeControllerDelegate, ASDataControllerSource, _ASTableViewCellDelegate, ASCellNodeInteractionDelegate, ASDelegateProxyInterceptor, ASBatchFetchingScrollView>
{ {
ASTableViewProxy *_proxyDataSource; ASTableViewProxy *_proxyDataSource;
ASTableViewProxy *_proxyDelegate; ASTableViewProxy *_proxyDelegate;
@ -286,8 +286,22 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
#pragma mark - #pragma mark -
#pragma mark Lifecycle #pragma mark Lifecycle
- (void)configureWithDataControllerClass:(Class)dataControllerClass eventLog:(ASEventLog *)eventLog - (instancetype)initWithFrame:(CGRect)frame style:(UITableViewStyle)style
{ {
return [self _initWithFrame:frame style:style dataControllerClass:nil owningNode:nil eventLog:nil];
}
- (instancetype)_initWithFrame:(CGRect)frame style:(UITableViewStyle)style dataControllerClass:(Class)dataControllerClass owningNode:(ASTableNode *)tableNode eventLog:(ASEventLog *)eventLog
{
if (!(self = [super initWithFrame:frame style:style])) {
return nil;
}
_cellsForVisibilityUpdates = [NSMutableSet set];
_cellsForLayoutUpdates = [NSMutableSet set];
if (!dataControllerClass) {
dataControllerClass = [[self class] dataControllerClass];
}
_layoutController = [[ASTableLayoutController alloc] initWithTableView:self]; _layoutController = [[ASTableLayoutController alloc] initWithTableView:self];
_rangeController = [[ASRangeController alloc] init]; _rangeController = [[ASRangeController alloc] init];
@ -295,13 +309,12 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
_rangeController.dataSource = self; _rangeController.dataSource = self;
_rangeController.delegate = self; _rangeController.delegate = self;
_dataController = [[dataControllerClass alloc] initWithDataSource:self eventLog:eventLog]; _dataController = [[dataControllerClass alloc] initWithDataSource:self node:tableNode eventLog:eventLog];
_dataController.delegate = _rangeController; _dataController.delegate = _rangeController;
_dataController.environmentDelegate = self;
_leadingScreensForBatching = 2.0; _leadingScreensForBatching = 2.0;
_batchContext = [[ASBatchContext alloc] init]; _batchContext = [[ASBatchContext alloc] init];
_automaticallyAdjustsContentOffset = NO; _automaticallyAdjustsContentOffset = NO;
_nodesConstrainedWidth = self.bounds.size.width; _nodesConstrainedWidth = self.bounds.size.width;
@ -313,25 +326,6 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
super.dataSource = (id<UITableViewDataSource>)_proxyDataSource; super.dataSource = (id<UITableViewDataSource>)_proxyDataSource;
[self registerClass:_ASTableViewCell.class forCellReuseIdentifier:kCellReuseIdentifier]; [self registerClass:_ASTableViewCell.class forCellReuseIdentifier:kCellReuseIdentifier];
}
- (instancetype)initWithFrame:(CGRect)frame style:(UITableViewStyle)style
{
return [self _initWithFrame:frame style:style dataControllerClass:nil eventLog:nil];
}
- (instancetype)_initWithFrame:(CGRect)frame style:(UITableViewStyle)style dataControllerClass:(Class)dataControllerClass eventLog:(ASEventLog *)eventLog
{
if (!(self = [super initWithFrame:frame style:style])) {
return nil;
}
_cellsForVisibilityUpdates = [NSMutableSet set];
_cellsForLayoutUpdates = [NSMutableSet set];
if (!dataControllerClass) {
dataControllerClass = [[self class] dataControllerClass];
}
[self configureWithDataControllerClass:dataControllerClass eventLog:eventLog];
if (!AS_AT_LEAST_IOS9) { if (!AS_AT_LEAST_IOS9) {
_retainedLayer = self.layer; _retainedLayer = self.layer;
@ -1734,13 +1728,6 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
return (fabs(rect.size.height - size.height) < FLT_EPSILON); return (fabs(rect.size.height - size.height) < FLT_EPSILON);
} }
#pragma mark - ASDataControllerEnvironmentDelegate
- (id<ASTraitEnvironment>)dataControllerEnvironment
{
return self.tableNode;
}
#pragma mark - _ASTableViewCellDelegate #pragma mark - _ASTableViewCellDelegate
- (void)didLayoutSubviewsOfTableViewCell:(_ASTableViewCell *)tableViewCell - (void)didLayoutSubviewsOfTableViewCell:(_ASTableViewCell *)tableViewCell

View File

@ -40,7 +40,7 @@
* *
* @param eventLog An event log passed through to the data controller. * @param eventLog An event log passed through to the data controller.
*/ */
- (instancetype)_initWithFrame:(CGRect)frame style:(UITableViewStyle)style dataControllerClass:(Class)dataControllerClass eventLog:(ASEventLog *)eventLog; - (instancetype)_initWithFrame:(CGRect)frame style:(UITableViewStyle)style dataControllerClass:(Class)dataControllerClass owningNode:(ASTableNode *)tableNode eventLog:(ASEventLog *)eventLog;
/// Set YES and we'll log every time we call [super insertRows…] etc /// Set YES and we'll log every time we call [super insertRows…] etc
@property (nonatomic) BOOL test_enableSuperUpdateCallLogging; @property (nonatomic) BOOL test_enableSuperUpdateCallLogging;

View File

@ -43,6 +43,7 @@
#import <AsyncDisplayKit/ASCollectionViewLayoutInspector.h> #import <AsyncDisplayKit/ASCollectionViewLayoutInspector.h>
#import <AsyncDisplayKit/ASCollectionViewLayoutFacilitatorProtocol.h> #import <AsyncDisplayKit/ASCollectionViewLayoutFacilitatorProtocol.h>
#import <AsyncDisplayKit/ASCellNode.h> #import <AsyncDisplayKit/ASCellNode.h>
#import <AsyncDisplayKit/ASRangeManagingNode.h>
#import <AsyncDisplayKit/ASSectionContext.h> #import <AsyncDisplayKit/ASSectionContext.h>
#import <AsyncDisplayKit/ASElementMap.h> #import <AsyncDisplayKit/ASElementMap.h>

View File

@ -19,6 +19,7 @@
#import <AsyncDisplayKit/ASTraitCollection.h> #import <AsyncDisplayKit/ASTraitCollection.h>
@class ASDisplayNode; @class ASDisplayNode;
@protocol ASRangeManagingNode;
NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_BEGIN
@ -28,13 +29,13 @@ AS_SUBCLASSING_RESTRICTED
//TODO change this to be a generic "kind" or "elementKind" that exposes `nil` for row kind //TODO change this to be a generic "kind" or "elementKind" that exposes `nil` for row kind
@property (nonatomic, readonly, copy, nullable) NSString *supplementaryElementKind; @property (nonatomic, readonly, copy, nullable) NSString *supplementaryElementKind;
@property (nonatomic, assign) ASSizeRange constrainedSize; @property (nonatomic, assign) ASSizeRange constrainedSize;
@property (nonatomic, weak) ASDisplayNode *owningNode; @property (nonatomic, readonly, weak) id<ASRangeManagingNode> owningNode;
@property (nonatomic, assign) ASPrimitiveTraitCollection traitCollection; @property (nonatomic, assign) ASPrimitiveTraitCollection traitCollection;
- (instancetype)initWithNodeBlock:(ASCellNodeBlock)nodeBlock - (instancetype)initWithNodeBlock:(ASCellNodeBlock)nodeBlock
supplementaryElementKind:(nullable NSString *)supplementaryElementKind supplementaryElementKind:(nullable NSString *)supplementaryElementKind
constrainedSize:(ASSizeRange)constrainedSize constrainedSize:(ASSizeRange)constrainedSize
owningNode:(ASDisplayNode *)owningNode owningNode:(id<ASRangeManagingNode>)owningNode
traitCollection:(ASPrimitiveTraitCollection)traitCollection; traitCollection:(ASPrimitiveTraitCollection)traitCollection;
/** /**

View File

@ -34,7 +34,7 @@
- (instancetype)initWithNodeBlock:(ASCellNodeBlock)nodeBlock - (instancetype)initWithNodeBlock:(ASCellNodeBlock)nodeBlock
supplementaryElementKind:(NSString *)supplementaryElementKind supplementaryElementKind:(NSString *)supplementaryElementKind
constrainedSize:(ASSizeRange)constrainedSize constrainedSize:(ASSizeRange)constrainedSize
owningNode:(ASDisplayNode *)owningNode owningNode:(id<ASRangeManagingNode>)owningNode
traitCollection:(ASPrimitiveTraitCollection)traitCollection traitCollection:(ASPrimitiveTraitCollection)traitCollection
{ {
NSAssert(nodeBlock != nil, @"Node block must not be nil"); NSAssert(nodeBlock != nil, @"Node block must not be nil");

View File

@ -25,7 +25,7 @@ NS_ASSUME_NONNULL_BEGIN
@class ASRangeController; @class ASRangeController;
@interface ASCollectionView () @interface ASCollectionView ()
- (instancetype)_initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout layoutFacilitator:(nullable id<ASCollectionViewLayoutFacilitatorProtocol>)layoutFacilitator eventLog:(nullable ASEventLog *)eventLog; - (instancetype)_initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout layoutFacilitator:(nullable id<ASCollectionViewLayoutFacilitatorProtocol>)layoutFacilitator owningNode:(nullable ASCollectionNode *)owningNode eventLog:(nullable ASEventLog *)eventLog;
@property (nonatomic, weak, readwrite) ASCollectionNode *collectionNode; @property (nonatomic, weak, readwrite) ASCollectionNode *collectionNode;
@property (nonatomic, strong, readonly) ASDataController *dataController; @property (nonatomic, strong, readonly) ASDataController *dataController;

View File

@ -39,6 +39,7 @@ NS_ASSUME_NONNULL_BEGIN
@class ASElementMap; @class ASElementMap;
@class ASLayout; @class ASLayout;
@class _ASHierarchyChangeSet; @class _ASHierarchyChangeSet;
@protocol ASRangeManagingNode;
@protocol ASTraitEnvironment; @protocol ASTraitEnvironment;
@protocol ASSectionContext; @protocol ASSectionContext;
@ -96,12 +97,6 @@ extern NSString * const ASCollectionInvalidUpdateException;
@end @end
@protocol ASDataControllerEnvironmentDelegate
- (nullable id<ASTraitEnvironment>)dataControllerEnvironment;
@end
/** /**
Delegate for notify the data updating of data controller. Delegate for notify the data updating of data controller.
These methods will be invoked from main thread right now, but it may be moved to background thread in the future. These methods will be invoked from main thread right now, but it may be moved to background thread in the future.
@ -160,17 +155,30 @@ extern NSString * const ASCollectionInvalidUpdateException;
*/ */
@interface ASDataController : NSObject @interface ASDataController : NSObject
- (instancetype)initWithDataSource:(id<ASDataControllerSource>)dataSource eventLog:(nullable ASEventLog *)eventLog NS_DESIGNATED_INITIALIZER; - (instancetype)initWithDataSource:(id<ASDataControllerSource>)dataSource node:(nullable id<ASRangeManagingNode>)node eventLog:(nullable ASEventLog *)eventLog NS_DESIGNATED_INITIALIZER;
- (instancetype)init NS_UNAVAILABLE;
/**
* The node that owns this data controller, if any.
*
* NOTE: Soon we will drop support for using ASTableView/ASCollectionView without the node, so this will be non-null.
*/
@property (nonatomic, nullable, weak, readonly) id<ASRangeManagingNode> node;
/** /**
* The map that is currently displayed. The "UIKit index space." * The map that is currently displayed. The "UIKit index space."
*
* This property will only be changed on the main thread.
*/ */
@property (nonatomic, strong, readonly) ASElementMap *visibleMap; @property (atomic, copy, readonly) ASElementMap *visibleMap;
/** /**
* The latest map fetched from the data source. May be more recent than @c visibleMap. * The latest map fetched from the data source. May be more recent than @c visibleMap.
*
* This property will only be changed on the main thread.
*/ */
@property (nonatomic, strong, readonly) ASElementMap *pendingMap; @property (atomic, copy, readonly) ASElementMap *pendingMap;
/** /**
Data source for fetching data info. Data source for fetching data info.
@ -187,11 +195,6 @@ extern NSString * const ASCollectionInvalidUpdateException;
*/ */
@property (nonatomic, weak) id<ASDataControllerDelegate> delegate; @property (nonatomic, weak) id<ASDataControllerDelegate> delegate;
/**
*
*/
@property (nonatomic, weak) id<ASDataControllerEnvironmentDelegate> environmentDelegate;
/** /**
* Delegate for preparing layouts. Main thead only. * Delegate for preparing layouts. Main thead only.
*/ */

View File

@ -27,6 +27,7 @@
#import <AsyncDisplayKit/ASLayout.h> #import <AsyncDisplayKit/ASLayout.h>
#import <AsyncDisplayKit/ASMainSerialQueue.h> #import <AsyncDisplayKit/ASMainSerialQueue.h>
#import <AsyncDisplayKit/ASMutableElementMap.h> #import <AsyncDisplayKit/ASMutableElementMap.h>
#import <AsyncDisplayKit/ASRangeManagingNode.h>
#import <AsyncDisplayKit/ASThread.h> #import <AsyncDisplayKit/ASThread.h>
#import <AsyncDisplayKit/ASTwoDimensionalArrayUtils.h> #import <AsyncDisplayKit/ASTwoDimensionalArrayUtils.h>
#import <AsyncDisplayKit/ASSection.h> #import <AsyncDisplayKit/ASSection.h>
@ -85,18 +86,21 @@ typedef void (^ASDataControllerCompletionBlock)(NSArray<ASCollectionElement *> *
} _dataSourceFlags; } _dataSourceFlags;
} }
@property (atomic, copy, readwrite) ASElementMap *pendingMap;
@property (atomic, copy, readwrite) ASElementMap *visibleMap;
@end @end
@implementation ASDataController @implementation ASDataController
#pragma mark - Lifecycle #pragma mark - Lifecycle
- (instancetype)initWithDataSource:(id<ASDataControllerSource>)dataSource eventLog:(ASEventLog *)eventLog - (instancetype)initWithDataSource:(id<ASDataControllerSource>)dataSource node:(nullable id<ASRangeManagingNode>)node eventLog:(ASEventLog *)eventLog
{ {
if (!(self = [super init])) { if (!(self = [super init])) {
return nil; return nil;
} }
_node = node;
_dataSource = dataSource; _dataSource = dataSource;
_dataSourceFlags.supplementaryNodeKindsInSections = [_dataSource respondsToSelector:@selector(dataController:supplementaryNodeKindsInSections:)]; _dataSourceFlags.supplementaryNodeKindsInSections = [_dataSource respondsToSelector:@selector(dataController:supplementaryNodeKindsInSections:)];
@ -110,7 +114,7 @@ typedef void (^ASDataControllerCompletionBlock)(NSArray<ASCollectionElement *> *
_eventLog = eventLog; _eventLog = eventLog;
#endif #endif
_visibleMap = _pendingMap = [[ASElementMap alloc] init]; self.visibleMap = self.pendingMap = [[ASElementMap alloc] init];
_nextSectionID = 0; _nextSectionID = 0;
@ -124,14 +128,6 @@ typedef void (^ASDataControllerCompletionBlock)(NSArray<ASCollectionElement *> *
return self; return self;
} }
- (instancetype)init
{
ASDisplayNodeFailAssert(@"Failed to call designated initializer.");
id<ASDataControllerSource> fakeDataSource = nil;
ASEventLog *eventLog = nil;
return [self initWithDataSource:fakeDataSource eventLog:eventLog];
}
+ (NSUInteger)parallelProcessorCount + (NSUInteger)parallelProcessorCount
{ {
static NSUInteger parallelProcessorCount; static NSUInteger parallelProcessorCount;
@ -277,9 +273,10 @@ typedef void (^ASDataControllerCompletionBlock)(NSArray<ASCollectionElement *> *
} }
}]; }];
} else if (_dataSourceFlags.supplementaryNodesOfKindInSection) { } else if (_dataSourceFlags.supplementaryNodesOfKindInSection) {
id<ASDataControllerSource> dataSource = _dataSource;
[sections enumerateRangesUsingBlock:^(NSRange range, BOOL * _Nonnull stop) { [sections enumerateRangesUsingBlock:^(NSRange range, BOOL * _Nonnull stop) {
for (NSUInteger sectionIndex = range.location; sectionIndex < NSMaxRange(range); sectionIndex++) { for (NSUInteger sectionIndex = range.location; sectionIndex < NSMaxRange(range); sectionIndex++) {
NSUInteger itemCount = [_dataSource dataController:self supplementaryNodesOfKind:kind inSection:sectionIndex]; NSUInteger itemCount = [dataSource dataController:self supplementaryNodesOfKind:kind inSection:sectionIndex];
for (NSUInteger i = 0; i < itemCount; i++) { for (NSUInteger i = 0; i < itemCount; i++) {
[indexPaths addObject:[NSIndexPath indexPathForItem:i inSection:sectionIndex]]; [indexPaths addObject:[NSIndexPath indexPathForItem:i inSection:sectionIndex]];
} }
@ -296,7 +293,6 @@ typedef void (^ASDataControllerCompletionBlock)(NSArray<ASCollectionElement *> *
* @param map The element map into which to apply the change. * @param map The element map into which to apply the change.
* @param indexPaths The index paths belongs to sections whose supplementary nodes need to be repopulated. * @param indexPaths The index paths belongs to sections whose supplementary nodes need to be repopulated.
* @param changeSet The changeset that triggered this repopulation. * @param changeSet The changeset that triggered this repopulation.
* @param owningNode The node that owns the new elements.
* @param traitCollection The trait collection needed to initialize elements * @param traitCollection The trait collection needed to initialize elements
* @param indexPathsAreNew YES if index paths are "after the update," NO otherwise. * @param indexPathsAreNew YES if index paths are "after the update," NO otherwise.
* @param shouldFetchSizeRanges Whether constrained sizes should be fetched from data source * @param shouldFetchSizeRanges Whether constrained sizes should be fetched from data source
@ -304,7 +300,6 @@ typedef void (^ASDataControllerCompletionBlock)(NSArray<ASCollectionElement *> *
- (void)_repopulateSupplementaryNodesIntoMap:(ASMutableElementMap *)map - (void)_repopulateSupplementaryNodesIntoMap:(ASMutableElementMap *)map
forSectionsContainingIndexPaths:(NSArray<NSIndexPath *> *)indexPaths forSectionsContainingIndexPaths:(NSArray<NSIndexPath *> *)indexPaths
changeSet:(_ASHierarchyChangeSet *)changeSet changeSet:(_ASHierarchyChangeSet *)changeSet
owningNode:(ASDisplayNode *)owningNode
traitCollection:(ASPrimitiveTraitCollection)traitCollection traitCollection:(ASPrimitiveTraitCollection)traitCollection
indexPathsAreNew:(BOOL)indexPathsAreNew indexPathsAreNew:(BOOL)indexPathsAreNew
shouldFetchSizeRanges:(BOOL)shouldFetchSizeRanges shouldFetchSizeRanges:(BOOL)shouldFetchSizeRanges
@ -330,7 +325,7 @@ typedef void (^ASDataControllerCompletionBlock)(NSArray<ASCollectionElement *> *
} }
for (NSString *kind in [self supplementaryKindsInSections:newSections]) { for (NSString *kind in [self supplementaryKindsInSections:newSections]) {
[self _insertElementsIntoMap:map kind:kind forSections:newSections owningNode:owningNode traitCollection:traitCollection shouldFetchSizeRanges:shouldFetchSizeRanges]; [self _insertElementsIntoMap:map kind:kind forSections:newSections traitCollection:traitCollection shouldFetchSizeRanges:shouldFetchSizeRanges];
} }
} }
@ -346,7 +341,6 @@ typedef void (^ASDataControllerCompletionBlock)(NSArray<ASCollectionElement *> *
- (void)_insertElementsIntoMap:(ASMutableElementMap *)map - (void)_insertElementsIntoMap:(ASMutableElementMap *)map
kind:(NSString *)kind kind:(NSString *)kind
forSections:(NSIndexSet *)sections forSections:(NSIndexSet *)sections
owningNode:(ASDisplayNode *)owningNode
traitCollection:(ASPrimitiveTraitCollection)traitCollection traitCollection:(ASPrimitiveTraitCollection)traitCollection
shouldFetchSizeRanges:(BOOL)shouldFetchSizeRanges shouldFetchSizeRanges:(BOOL)shouldFetchSizeRanges
{ {
@ -357,7 +351,7 @@ typedef void (^ASDataControllerCompletionBlock)(NSArray<ASCollectionElement *> *
} }
NSArray<NSIndexPath *> *indexPaths = [self _allIndexPathsForItemsOfKind:kind inSections:sections]; NSArray<NSIndexPath *> *indexPaths = [self _allIndexPathsForItemsOfKind:kind inSections:sections];
[self _insertElementsIntoMap:map kind:kind atIndexPaths:indexPaths owningNode:owningNode traitCollection:traitCollection shouldFetchSizeRanges:shouldFetchSizeRanges]; [self _insertElementsIntoMap:map kind:kind atIndexPaths:indexPaths traitCollection:traitCollection shouldFetchSizeRanges:shouldFetchSizeRanges];
} }
/** /**
@ -373,7 +367,6 @@ typedef void (^ASDataControllerCompletionBlock)(NSArray<ASCollectionElement *> *
- (void)_insertElementsIntoMap:(ASMutableElementMap *)map - (void)_insertElementsIntoMap:(ASMutableElementMap *)map
kind:(NSString *)kind kind:(NSString *)kind
atIndexPaths:(NSArray<NSIndexPath *> *)indexPaths atIndexPaths:(NSArray<NSIndexPath *> *)indexPaths
owningNode:(ASDisplayNode *)owningNode
traitCollection:(ASPrimitiveTraitCollection)traitCollection traitCollection:(ASPrimitiveTraitCollection)traitCollection
shouldFetchSizeRanges:(BOOL)shouldFetchSizeRanges shouldFetchSizeRanges:(BOOL)shouldFetchSizeRanges
{ {
@ -390,12 +383,14 @@ typedef void (^ASDataControllerCompletionBlock)(NSArray<ASCollectionElement *> *
} }
LOG(@"Populating elements of kind: %@, for index paths: %@", kind, indexPaths); LOG(@"Populating elements of kind: %@, for index paths: %@", kind, indexPaths);
id<ASDataControllerSource> dataSource = self.dataSource;
id<ASRangeManagingNode> node = self.node;
for (NSIndexPath *indexPath in indexPaths) { for (NSIndexPath *indexPath in indexPaths) {
ASCellNodeBlock nodeBlock; ASCellNodeBlock nodeBlock;
if (isRowKind) { if (isRowKind) {
nodeBlock = [_dataSource dataController:self nodeBlockAtIndexPath:indexPath]; nodeBlock = [dataSource dataController:self nodeBlockAtIndexPath:indexPath];
} else { } else {
nodeBlock = [_dataSource dataController:self supplementaryNodeBlockOfKind:kind atIndexPath:indexPath]; nodeBlock = [dataSource dataController:self supplementaryNodeBlockOfKind:kind atIndexPath:indexPath];
} }
ASSizeRange constrainedSize; ASSizeRange constrainedSize;
@ -406,7 +401,7 @@ typedef void (^ASDataControllerCompletionBlock)(NSArray<ASCollectionElement *> *
ASCollectionElement *element = [[ASCollectionElement alloc] initWithNodeBlock:nodeBlock ASCollectionElement *element = [[ASCollectionElement alloc] initWithNodeBlock:nodeBlock
supplementaryElementKind:isRowKind ? nil : kind supplementaryElementKind:isRowKind ? nil : kind
constrainedSize:constrainedSize constrainedSize:constrainedSize
owningNode:owningNode owningNode:node
traitCollection:traitCollection]; traitCollection:traitCollection];
[map insertElement:element atIndexPath:indexPath]; [map insertElement:element atIndexPath:indexPath];
} }
@ -544,14 +539,12 @@ typedef void (^ASDataControllerCompletionBlock)(NSArray<ASCollectionElement *> *
// Step 1: Update the mutable copies to match the data source's state // Step 1: Update the mutable copies to match the data source's state
[self _updateSectionContextsInMap:mutableMap changeSet:changeSet]; [self _updateSectionContextsInMap:mutableMap changeSet:changeSet];
__weak id<ASTraitEnvironment> environment = [self.environmentDelegate dataControllerEnvironment]; ASPrimitiveTraitCollection existingTraitCollection = [self.node primitiveTraitCollection];
__weak ASDisplayNode *owningNode = (ASDisplayNode *)environment; // This is gross! [self _updateElementsInMap:mutableMap changeSet:changeSet traitCollection:existingTraitCollection shouldFetchSizeRanges:(! canDelegateLayout)];
ASPrimitiveTraitCollection existingTraitCollection = [environment primitiveTraitCollection];
[self _updateElementsInMap:mutableMap changeSet:changeSet owningNode:owningNode traitCollection:existingTraitCollection shouldFetchSizeRanges:(! canDelegateLayout)];
// Step 2: Clone the new data // Step 2: Clone the new data
ASElementMap *newMap = [mutableMap copy]; ASElementMap *newMap = [mutableMap copy];
_pendingMap = newMap; self.pendingMap = newMap;
// Step 3: Ask layout delegate for contexts // Step 3: Ask layout delegate for contexts
id layoutContext = nil; id layoutContext = nil;
@ -585,7 +578,7 @@ typedef void (^ASDataControllerCompletionBlock)(NSArray<ASCollectionElement *> *
[_delegate dataController:self willUpdateWithChangeSet:changeSet]; [_delegate dataController:self willUpdateWithChangeSet:changeSet];
// Step 5: Deploy the new data as "completed" and inform delegate // Step 5: Deploy the new data as "completed" and inform delegate
_visibleMap = newMap; self.visibleMap = newMap;
[_delegate dataController:self didUpdateWithChangeSet:changeSet]; [_delegate dataController:self didUpdateWithChangeSet:changeSet];
}]; }];
@ -644,7 +637,6 @@ typedef void (^ASDataControllerCompletionBlock)(NSArray<ASCollectionElement *> *
*/ */
- (void)_updateElementsInMap:(ASMutableElementMap *)map - (void)_updateElementsInMap:(ASMutableElementMap *)map
changeSet:(_ASHierarchyChangeSet *)changeSet changeSet:(_ASHierarchyChangeSet *)changeSet
owningNode:(ASDisplayNode *)owningNode
traitCollection:(ASPrimitiveTraitCollection)traitCollection traitCollection:(ASPrimitiveTraitCollection)traitCollection
shouldFetchSizeRanges:(BOOL)shouldFetchSizeRanges shouldFetchSizeRanges:(BOOL)shouldFetchSizeRanges
{ {
@ -656,7 +648,7 @@ typedef void (^ASDataControllerCompletionBlock)(NSArray<ASCollectionElement *> *
NSUInteger sectionCount = [self itemCountsFromDataSource].size(); NSUInteger sectionCount = [self itemCountsFromDataSource].size();
if (sectionCount > 0) { if (sectionCount > 0) {
NSIndexSet *sectionIndexes = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, sectionCount)]; NSIndexSet *sectionIndexes = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, sectionCount)];
[self _insertElementsIntoMap:map sections:sectionIndexes owningNode:owningNode traitCollection:traitCollection shouldFetchSizeRanges:shouldFetchSizeRanges]; [self _insertElementsIntoMap:map sections:sectionIndexes traitCollection:traitCollection shouldFetchSizeRanges:shouldFetchSizeRanges];
} }
// Return immediately because reloadData can't be used in conjuntion with other updates. // Return immediately because reloadData can't be used in conjuntion with other updates.
return; return;
@ -667,7 +659,6 @@ typedef void (^ASDataControllerCompletionBlock)(NSArray<ASCollectionElement *> *
// Aggressively repopulate supplementary nodes (#1773 & #1629) // Aggressively repopulate supplementary nodes (#1773 & #1629)
[self _repopulateSupplementaryNodesIntoMap:map forSectionsContainingIndexPaths:change.indexPaths [self _repopulateSupplementaryNodesIntoMap:map forSectionsContainingIndexPaths:change.indexPaths
changeSet:changeSet changeSet:changeSet
owningNode:owningNode
traitCollection:traitCollection traitCollection:traitCollection
indexPathsAreNew:NO indexPathsAreNew:NO
shouldFetchSizeRanges:shouldFetchSizeRanges]; shouldFetchSizeRanges:shouldFetchSizeRanges];
@ -680,15 +671,14 @@ typedef void (^ASDataControllerCompletionBlock)(NSArray<ASCollectionElement *> *
} }
for (_ASHierarchySectionChange *change in [changeSet sectionChangesOfType:_ASHierarchyChangeTypeInsert]) { for (_ASHierarchySectionChange *change in [changeSet sectionChangesOfType:_ASHierarchyChangeTypeInsert]) {
[self _insertElementsIntoMap:map sections:change.indexSet owningNode:owningNode traitCollection:traitCollection shouldFetchSizeRanges:shouldFetchSizeRanges]; [self _insertElementsIntoMap:map sections:change.indexSet traitCollection:traitCollection shouldFetchSizeRanges:shouldFetchSizeRanges];
} }
for (_ASHierarchyItemChange *change in [changeSet itemChangesOfType:_ASHierarchyChangeTypeInsert]) { for (_ASHierarchyItemChange *change in [changeSet itemChangesOfType:_ASHierarchyChangeTypeInsert]) {
[self _insertElementsIntoMap:map kind:ASDataControllerRowNodeKind atIndexPaths:change.indexPaths owningNode:owningNode traitCollection:traitCollection shouldFetchSizeRanges:shouldFetchSizeRanges]; [self _insertElementsIntoMap:map kind:ASDataControllerRowNodeKind atIndexPaths:change.indexPaths traitCollection:traitCollection shouldFetchSizeRanges:shouldFetchSizeRanges];
// Aggressively reload supplementary nodes (#1773 & #1629) // Aggressively reload supplementary nodes (#1773 & #1629)
[self _repopulateSupplementaryNodesIntoMap:map forSectionsContainingIndexPaths:change.indexPaths [self _repopulateSupplementaryNodesIntoMap:map forSectionsContainingIndexPaths:change.indexPaths
changeSet:changeSet changeSet:changeSet
owningNode:owningNode
traitCollection:traitCollection traitCollection:traitCollection
indexPathsAreNew:YES indexPathsAreNew:YES
shouldFetchSizeRanges:shouldFetchSizeRanges]; shouldFetchSizeRanges:shouldFetchSizeRanges];
@ -697,7 +687,6 @@ typedef void (^ASDataControllerCompletionBlock)(NSArray<ASCollectionElement *> *
- (void)_insertElementsIntoMap:(ASMutableElementMap *)map - (void)_insertElementsIntoMap:(ASMutableElementMap *)map
sections:(NSIndexSet *)sectionIndexes sections:(NSIndexSet *)sectionIndexes
owningNode:(ASDisplayNode *)owningNode
traitCollection:(ASPrimitiveTraitCollection)traitCollection traitCollection:(ASPrimitiveTraitCollection)traitCollection
shouldFetchSizeRanges:(BOOL)shouldFetchSizeRanges shouldFetchSizeRanges:(BOOL)shouldFetchSizeRanges
{ {
@ -709,12 +698,12 @@ typedef void (^ASDataControllerCompletionBlock)(NSArray<ASCollectionElement *> *
// Items // Items
[map insertEmptySectionsOfItemsAtIndexes:sectionIndexes]; [map insertEmptySectionsOfItemsAtIndexes:sectionIndexes];
[self _insertElementsIntoMap:map kind:ASDataControllerRowNodeKind forSections:sectionIndexes owningNode:owningNode traitCollection:traitCollection shouldFetchSizeRanges:shouldFetchSizeRanges]; [self _insertElementsIntoMap:map kind:ASDataControllerRowNodeKind forSections:sectionIndexes traitCollection:traitCollection shouldFetchSizeRanges:shouldFetchSizeRanges];
// Supplementaries // Supplementaries
for (NSString *kind in [self supplementaryKindsInSections:sectionIndexes]) { for (NSString *kind in [self supplementaryKindsInSections:sectionIndexes]) {
// Step 2: Populate new elements for all sections // Step 2: Populate new elements for all sections
[self _insertElementsIntoMap:map kind:kind forSections:sectionIndexes owningNode:owningNode traitCollection:traitCollection shouldFetchSizeRanges:shouldFetchSizeRanges]; [self _insertElementsIntoMap:map kind:kind forSections:sectionIndexes traitCollection:traitCollection shouldFetchSizeRanges:shouldFetchSizeRanges];
} }
} }
@ -729,10 +718,11 @@ typedef void (^ASDataControllerCompletionBlock)(NSArray<ASCollectionElement *> *
return; return;
} }
id<ASDataControllerSource> dataSource = self.dataSource;
for (ASCellNode *node in nodes) { for (ASCellNode *node in nodes) {
ASSizeRange constrainedSize = [self constrainedSizeForElement:node.collectionElement inElementMap:_pendingMap]; ASSizeRange constrainedSize = [self constrainedSizeForElement:node.collectionElement inElementMap:_pendingMap];
[self _layoutNode:node withConstrainedSize:constrainedSize]; [self _layoutNode:node withConstrainedSize:constrainedSize];
BOOL matchesSize = [_dataSource dataController:self presentedSizeForElement:node.collectionElement matchesSize:node.frame.size]; BOOL matchesSize = [dataSource dataController:self presentedSizeForElement:node.collectionElement matchesSize:node.frame.size];
if (! matchesSize) { if (! matchesSize) {
[nodesSizesChanged addObject:node]; [nodesSizesChanged addObject:node];
} }
@ -783,8 +773,9 @@ typedef void (^ASDataControllerCompletionBlock)(NSArray<ASCollectionElement *> *
// Can't update the trait collection right away because _visibleMap may not be up-to-date, // Can't update the trait collection right away because _visibleMap may not be up-to-date,
// i.e there might be some elements that were allocated using the old trait collection but haven't been added to _visibleMap // i.e there might be some elements that were allocated using the old trait collection but haven't been added to _visibleMap
[self _scheduleBlockOnMainSerialQueue:^{ [self _scheduleBlockOnMainSerialQueue:^{
ASPrimitiveTraitCollection newTraitCollection = [[_environmentDelegate dataControllerEnvironment] primitiveTraitCollection]; ASPrimitiveTraitCollection newTraitCollection = [self.node primitiveTraitCollection];
for (ASCollectionElement *element in _visibleMap) { for (ASCollectionElement *element in _visibleMap) {
element.traitCollection = newTraitCollection; element.traitCollection = newTraitCollection;
} }

View File

@ -72,9 +72,9 @@ NS_ASSUME_NONNULL_BEGIN
*/ */
@property (nonatomic, strong, nullable) UICollectionViewLayoutAttributes *layoutAttributes; @property (nonatomic, strong, nullable) UICollectionViewLayoutAttributes *layoutAttributes;
@property (weak, nullable) ASCollectionElement *collectionElement; @property (atomic, weak, nullable) ASCollectionElement *collectionElement;
@property (nonatomic, weak, nullable) ASDisplayNode *owningNode; @property (atomic, weak, nullable) id<ASRangeManagingNode> owningNode;
@property (nonatomic, assign) BOOL shouldUseUIKitCell; @property (nonatomic, assign) BOOL shouldUseUIKitCell;

View File

@ -1,5 +1,5 @@
// //
// ASTableViewTests.m // ASTableViewTests.mm
// Texture // Texture
// //
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
@ -61,7 +61,7 @@
- (instancetype)__initWithFrame:(CGRect)frame style:(UITableViewStyle)style - (instancetype)__initWithFrame:(CGRect)frame style:(UITableViewStyle)style
{ {
return [super _initWithFrame:frame style:style dataControllerClass:[ASTestDataController class] eventLog:nil]; return [super _initWithFrame:frame style:style dataControllerClass:[ASTestDataController class] owningNode:nil eventLog:nil];
} }
- (ASTestDataController *)testDataController - (ASTestDataController *)testDataController