Skip to content
This repository was archived by the owner on Feb 2, 2023. It is now read-only.

Commit b3be451

Browse files
aaronschubert0Adlai Holler
authored andcommitted
[ASTableNode/ASCollectionNode] Inversion (#2891)
* Add inverted property to ASTableNode * Add inverted property to ASCollectionNode * Add example * De-inform data controller and use different CATransform3D * Add logic to pending state * Add accessor for inverted property
1 parent e69a475 commit b3be451

53 files changed

Lines changed: 1746 additions & 13 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

AsyncDisplayKit/ASCollectionNode.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,12 @@ NS_ASSUME_NONNULL_BEGIN
7474
*/
7575
@property (weak, nonatomic) id <ASCollectionDataSource> dataSource;
7676

77+
/*
78+
* A Boolean value that determines whether the collection node will be flipped.
79+
* If the value of this property is YES, the first cell node will be at the bottom of the collection node (as opposed to the top by default). This is useful for chat/messaging apps. The default value is NO.
80+
*/
81+
@property (nonatomic, assign) BOOL inverted;
82+
7783
/**
7884
* A Boolean value that indicates whether users can select items in the collection node.
7985
* If the value of this property is YES (the default), users can select items. If you want more fine-grained control over the selection of items, you must provide a delegate object and implement the appropriate methods of the UICollectionNodeDelegate protocol.

AsyncDisplayKit/ASCollectionNode.mm

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ @interface _ASCollectionPendingState : NSObject
3131
@property (nonatomic, assign) ASLayoutRangeMode rangeMode;
3232
@property (nonatomic, assign) BOOL allowsSelection; // default is YES
3333
@property (nonatomic, assign) BOOL allowsMultipleSelection; // default is NO
34+
@property (nonatomic, assign) BOOL inverted; //default is NO
3435
@end
3536

3637
@implementation _ASCollectionPendingState
@@ -42,6 +43,7 @@ - (instancetype)init
4243
_rangeMode = ASLayoutRangeModeCount;
4344
_allowsSelection = YES;
4445
_allowsMultipleSelection = NO;
46+
_inverted = NO;
4547
}
4648
return self;
4749
}
@@ -148,6 +150,7 @@ - (void)didLoad
148150
self.pendingState = nil;
149151
view.asyncDelegate = pendingState.delegate;
150152
view.asyncDataSource = pendingState.dataSource;
153+
view.inverted = pendingState.inverted;
151154
view.allowsSelection = pendingState.allowsSelection;
152155
view.allowsMultipleSelection = pendingState.allowsMultipleSelection;
153156

@@ -217,6 +220,26 @@ - (_ASCollectionPendingState *)pendingState
217220
return _pendingState;
218221
}
219222

223+
- (void)setInverted:(BOOL)inverted
224+
{
225+
self.transform = inverted ? CATransform3DMakeScale(1, -1, 1) : CATransform3DIdentity;
226+
if ([self pendingState]) {
227+
_pendingState.inverted = inverted;
228+
} else {
229+
ASDisplayNodeAssert([self isNodeLoaded], @"ASCollectionNode should be loaded if pendingState doesn't exist");
230+
self.view.inverted = inverted;
231+
}
232+
}
233+
234+
- (BOOL)inverted
235+
{
236+
if ([self pendingState]) {
237+
return _pendingState.inverted;
238+
} else {
239+
return self.view.inverted;
240+
}
241+
}
242+
220243
- (void)setDelegate:(id <ASCollectionDelegate>)delegate
221244
{
222245
if ([self pendingState]) {

AsyncDisplayKit/ASCollectionView.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,11 @@ NS_ASSUME_NONNULL_BEGIN
106106
*/
107107
@property (nonatomic, readonly) ASScrollDirection scrollableDirections;
108108

109+
/*
110+
* A Boolean value that determines whether the nodes that the data source renders will be flipped.
111+
*/
112+
@property (nonatomic, assign) BOOL inverted;
113+
109114
/**
110115
* Forces the .contentInset to be UIEdgeInsetsZero.
111116
*

AsyncDisplayKit/ASCollectionView.mm

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1408,6 +1408,9 @@ - (ASCellNodeBlock)dataController:(ASDataController *)dataController nodeBlockAt
14081408
if (node.interactionDelegate == nil) {
14091409
node.interactionDelegate = strongSelf;
14101410
}
1411+
if (_inverted) {
1412+
node.transform = CATransform3DMakeScale(1, -1, 1) ;
1413+
}
14111414
return node;
14121415
};
14131416
return block;

AsyncDisplayKit/ASTableNode.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@ NS_ASSUME_NONNULL_BEGIN
3535
@property (weak, nonatomic) id <ASTableDelegate> delegate;
3636
@property (weak, nonatomic) id <ASTableDataSource> dataSource;
3737

38+
/*
39+
* A Boolean value that determines whether the table will be flipped.
40+
* If the value of this property is YES, the first cell node will be at the bottom of the table (as opposed to the top by default). This is useful for chat/messaging apps. The default value is NO.
41+
*/
42+
@property (nonatomic, assign) BOOL inverted;
3843
/*
3944
* A Boolean value that determines whether users can select a row.
4045
* If the value of this property is YES (the default), users can select rows. If you set it to NO, they cannot select rows. Setting this property affects cell selection only when the table view is not in editing mode. If you want to restrict selection of cells in editing mode, use `allowsSelectionDuringEditing`.

AsyncDisplayKit/ASTableNode.mm

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ @interface _ASTablePendingState : NSObject
3030
@property (nonatomic, assign) BOOL allowsSelectionDuringEditing;
3131
@property (nonatomic, assign) BOOL allowsMultipleSelection;
3232
@property (nonatomic, assign) BOOL allowsMultipleSelectionDuringEditing;
33+
@property (nonatomic, assign) BOOL inverted;
3334
@end
3435

3536
@implementation _ASTablePendingState
@@ -42,6 +43,7 @@ - (instancetype)init
4243
_allowsSelectionDuringEditing = NO;
4344
_allowsMultipleSelection = NO;
4445
_allowsMultipleSelectionDuringEditing = NO;
46+
_inverted = NO;
4547
}
4648
return self;
4749
}
@@ -116,6 +118,7 @@ - (void)didLoad
116118
self.pendingState = nil;
117119
view.asyncDelegate = pendingState.delegate;
118120
view.asyncDataSource = pendingState.dataSource;
121+
view.inverted = pendingState.inverted;
119122
view.allowsSelection = pendingState.allowsSelection;
120123
view.allowsSelectionDuringEditing = pendingState.allowsSelectionDuringEditing;
121124
view.allowsMultipleSelection = pendingState.allowsMultipleSelection;
@@ -186,6 +189,26 @@ - (_ASTablePendingState *)pendingState
186189
return _pendingState;
187190
}
188191

192+
- (void)setInverted:(BOOL)inverted
193+
{
194+
self.transform = inverted ? CATransform3DMakeScale(1, -1, 1) : CATransform3DIdentity;
195+
if ([self pendingState]) {
196+
_pendingState.inverted = inverted;
197+
} else {
198+
ASDisplayNodeAssert([self isNodeLoaded], @"ASTableNode should be loaded if pendingState doesn't exist");
199+
self.view.inverted = inverted;
200+
}
201+
}
202+
203+
- (BOOL)inverted
204+
{
205+
if ([self pendingState]) {
206+
return _pendingState.inverted;
207+
} else {
208+
return self.view.inverted;
209+
}
210+
}
211+
189212
- (void)setDelegate:(id <ASTableDelegate>)delegate
190213
{
191214
if ([self pendingState]) {

AsyncDisplayKit/ASTableView.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,11 @@ NS_ASSUME_NONNULL_BEGIN
5959
*/
6060
@property (nonatomic, assign) CGFloat leadingScreensForBatching;
6161

62+
/*
63+
* A Boolean value that determines whether the nodes that the data source renders will be flipped.
64+
*/
65+
@property (nonatomic, assign) BOOL inverted;
66+
6267
@end
6368

6469
@interface ASTableView (Deprecated)

AsyncDisplayKit/ASTableView.mm

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1551,6 +1551,9 @@ - (ASCellNodeBlock)dataController:(ASDataController *)dataController nodeBlockAt
15511551
if (node.interactionDelegate == nil) {
15521552
node.interactionDelegate = strongSelf;
15531553
}
1554+
if (_inverted) {
1555+
node.transform = CATransform3DMakeScale(1, -1, 1) ;
1556+
}
15541557
return node;
15551558
};
15561559
return block;

AsyncDisplayKit/Details/ASDataController.mm

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -912,7 +912,6 @@ - (ASCellNode *)nodeAtIndexPath:(NSIndexPath *)indexPath
912912
context = completedNodesSection[row];
913913
}
914914
}
915-
916915
return context.node;
917916
}
918917

AsyncDisplayKit/Private/ASDisplayNode+UIViewBridge.mm

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -218,10 +218,10 @@ - (CGRect)frame
218218
_bridge_prologue_read;
219219

220220
// Frame is only defined when transform is identity.
221-
#if DEBUG
222-
// Checking if the transform is identity is expensive, so disable when unnecessary. We have assertions on in Release, so DEBUG is the only way I know of.
223-
ASDisplayNodeAssert(CATransform3DIsIdentity(self.transform), @"-[ASDisplayNode frame] - self.transform must be identity in order to use the frame property. (From Apple's UIView documentation: If the transform property is not the identity transform, the value of this property is undefined and therefore should be ignored.)");
224-
#endif
221+
//#if DEBUG
222+
// // Checking if the transform is identity is expensive, so disable when unnecessary. We have assertions on in Release, so DEBUG is the only way I know of.
223+
// ASDisplayNodeAssert(CATransform3DIsIdentity(self.transform), @"-[ASDisplayNode frame] - self.transform must be identity in order to use the frame property. (From Apple's UIView documentation: If the transform property is not the identity transform, the value of this property is undefined and therefore should be ignored.)");
224+
//#endif
225225

226226
CGPoint position = self.position;
227227
CGRect bounds = self.bounds;
@@ -277,10 +277,10 @@ - (void)setFrame:(CGRect)rect
277277
// We do have to set frame directly, and we're on main thread with a loaded node.
278278
// Just set the frame on the view.
279279
// NOTE: Frame is only defined when transform is identity because we explicitly diverge from CALayer behavior and define frame without transform.
280-
#if DEBUG
281-
// Checking if the transform is identity is expensive, so disable when unnecessary. We have assertions on in Release, so DEBUG is the only way I know of.
282-
ASDisplayNodeAssert(CATransform3DIsIdentity(self.transform), @"-[ASDisplayNode setFrame:] - self.transform must be identity in order to set the frame property. (From Apple's UIView documentation: If the transform property is not the identity transform, the value of this property is undefined and therefore should be ignored.)");
283-
#endif
280+
//#if DEBUG
281+
// // Checking if the transform is identity is expensive, so disable when unnecessary. We have assertions on in Release, so DEBUG is the only way I know of.
282+
// ASDisplayNodeAssert(CATransform3DIsIdentity(self.transform), @"-[ASDisplayNode setFrame:] - self.transform must be identity in order to set the frame property. (From Apple's UIView documentation: If the transform property is not the identity transform, the value of this property is undefined and therefore should be ignored.)");
283+
//#endif
284284
_view.frame = rect;
285285
} else {
286286
// We do have to set frame directly, but either the node isn't loaded or we're on a non-main thread.

0 commit comments

Comments
 (0)