Move Transition Layout API out of beta header and remove shouldMeasureAsync from API

shouldMeasureAsync is enabled by default now.
This commit is contained in:
Michael Schneider
2016-08-01 17:12:52 -07:00
parent 49b65fd783
commit 32058815f2
6 changed files with 132 additions and 69 deletions

View File

@@ -10,7 +10,10 @@
// of patent rights can be found in the PATENTS file in the same directory. // of patent rights can be found in the PATENTS file in the same directory.
// //
#import <AsyncDisplayKit/ASDisplayNode.h> #import <AsyncDisplayKit/ASDimension.h>
@class ASDisplayNode;
@class ASLayout;
NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_BEGIN

View File

@@ -8,7 +8,7 @@
// of patent rights can be found in the PATENTS file in the same directory. // of patent rights can be found in the PATENTS file in the same directory.
// //
#import "ASContextTransitioning.h" #import "ASDisplayNode.h"
#import "ASLayoutRangeType.h" #import "ASLayoutRangeType.h"
NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_BEGIN
@@ -65,63 +65,12 @@ ASDISPLAYNODE_EXTERN_C_END
@property (nonatomic) BOOL usesImplicitHierarchyManagement; @property (nonatomic) BOOL usesImplicitHierarchyManagement;
/**
* @discussion A place to perform your animation. New nodes have been inserted here. You can also use this time to re-order the hierarchy.
*/
- (void)animateLayoutTransition:(id<ASContextTransitioning>)context;
/**
* @discussion A place to clean up your nodes after the transition
*/
- (void)didCompleteLayoutTransition:(id<ASContextTransitioning>)context;
/**
* @abstract Transitions the current layout with a new constrained size. Must be called on main thread.
*
* @param animated Animation is optional, but will still proceed through your `animateLayoutTransition` implementation with `isAnimated == NO`.
*
* @param shouldMeasureAsync Measure the layout asynchronously.
*
* @param measurementCompletion Optional completion block called only if a new layout is calculated.
* It is called on main, right after the measurement and before -animateLayoutTransition:.
*
* @discussion If the passed constrainedSize is the the same as the node's current constrained size, this method is noop.
*
* @see animateLayoutTransition:
*/
- (void)transitionLayoutWithSizeRange:(ASSizeRange)constrainedSize
animated:(BOOL)animated
shouldMeasureAsync:(BOOL)shouldMeasureAsync
measurementCompletion:(nullable void(^)())completion;
/**
* @abstract Invalidates the current layout and begins a relayout of the node with the current `constrainedSize`. Must be called on main thread.
*
* @param animated Animation is optional, but will still proceed through your `animateLayoutTransition` implementation with `isAnimated == NO`.
*
* @param shouldMeasureAsync Measure the layout asynchronously.
*
* @param measurementCompletion Optional completion block called only if a new layout is calculated.
* It is called right after the measurement and before -animateLayoutTransition:.
*
* @see animateLayoutTransition:
*/
- (void)transitionLayoutWithAnimation:(BOOL)animated
shouldMeasureAsync:(BOOL)shouldMeasureAsync
measurementCompletion:(nullable void(^)())completion;
/** /**
* @abstract Currently used by ASNetworkImageNode and ASMultiplexImageNode to allow their placeholders to stay if they are loading an image from the network. * @abstract Currently used by ASNetworkImageNode and ASMultiplexImageNode to allow their placeholders to stay if they are loading an image from the network.
* Otherwise, a display pass is scheduled and completes, but does not actually draw anything - and ASDisplayNode considers the element finished. * Otherwise, a display pass is scheduled and completes, but does not actually draw anything - and ASDisplayNode considers the element finished.
*/ */
- (BOOL)placeholderShouldPersist; - (BOOL)placeholderShouldPersist;
/**
* @abstract Cancels all performing layout transitions. Can be called on any thread.
*/
- (void)cancelLayoutTransitionsInProgress;
/** /**
* @abstract Indicates that the receiver and all subnodes have finished displaying. May be called more than once, for example if the receiver has * @abstract Indicates that the receiver and all subnodes have finished displaying. May be called more than once, for example if the receiver has
* a network image node. This is called after the first display pass even if network image nodes have not downloaded anything (text would be done, * a network image node. This is called after the first display pass even if network image nodes have not downloaded anything (text would be done,

View File

@@ -16,6 +16,7 @@
#import <AsyncDisplayKit/ASDimension.h> #import <AsyncDisplayKit/ASDimension.h>
#import <AsyncDisplayKit/ASAsciiArtBoxCreator.h> #import <AsyncDisplayKit/ASAsciiArtBoxCreator.h>
#import <AsyncDisplayKit/ASLayoutable.h> #import <AsyncDisplayKit/ASLayoutable.h>
#import <AsyncDisplayKit/ASContextTransitioning.h>
#define ASDisplayNodeLoggingEnabled 0 #define ASDisplayNodeLoggingEnabled 0
@@ -744,6 +745,54 @@ NS_ASSUME_NONNULL_BEGIN
// Accessibility identification support // Accessibility identification support
@property (nonatomic, copy, nullable) NSString *accessibilityIdentifier; @property (nonatomic, copy, nullable) NSString *accessibilityIdentifier;
@end
@interface ASDisplayNode (LayoutTransitioning)
/**
* @discussion A place to perform your animation. New nodes have been inserted here. You can also use this time to re-order the hierarchy.
*/
- (void)animateLayoutTransition:(nonnull id<ASContextTransitioning>)context;
/**
* @discussion A place to clean up your nodes after the transition
*/
- (void)didCompleteLayoutTransition:(nonnull id<ASContextTransitioning>)context;
/**
* @abstract Transitions the current layout with a new constrained size. Must be called on main thread.
*
* @param animated Animation is optional, but will still proceed through your `animateLayoutTransition` implementation with `isAnimated == NO`.
* @param shouldMeasureAsync Measure the layout asynchronously.
* @param measurementCompletion Optional completion block called only if a new layout is calculated.
*
* @discussion It is called on main, right after the measurement and before -animateLayoutTransition:. If the passed constrainedSize is the the same as the node's current constrained size, this method is noop.
*
* @see animateLayoutTransition:
*/
- (void)transitionLayoutWithSizeRange:(ASSizeRange)constrainedSize
animated:(BOOL)animated
measurementCompletion:(nullable void(^)())completion;
/**
* @abstract Invalidates the current layout and begins a relayout of the node with the current `constrainedSize`. Must be called on main thread.
*
* @discussion It is called right after the measurement and before -animateLayoutTransition:.
*
* @param animated Animation is optional, but will still proceed through your `animateLayoutTransition` implementation with `isAnimated == NO`.
* @param measurementCompletion Optional completion block called only if a new layout is calculated.
*
* @see animateLayoutTransition:
*
*/
- (void)transitionLayoutAnimated:(BOOL)animated measurementCompletion:(nullable void(^)())completion;
/**
* @abstract Cancels all performing layout transitions. Can be called on any thread.
*/
- (void)cancelLayoutTransition;
@end @end
/* /*
@@ -776,6 +825,54 @@ NS_ASSUME_NONNULL_BEGIN
@interface ASDisplayNode (Deprecated) @interface ASDisplayNode (Deprecated)
/**
* @abstract Transitions the current layout with a new constrained size. Must be called on main thread.
*
* @param animated Animation is optional, but will still proceed through your `animateLayoutTransition` implementation with `isAnimated == NO`.
* @param shouldMeasureAsync Measure the layout asynchronously.
* @param measurementCompletion Optional completion block called only if a new layout is calculated.
* It is called on main, right after the measurement and before -animateLayoutTransition:.
*
* @discussion If the passed constrainedSize is the the same as the node's current constrained size, this method is noop.
*
* @see animateLayoutTransition:
*
* @deprecated Deprecated in version 2.0: Use transitionLayoutWithSizeRange:animated:measurementCompletion:.
* shouldMeasureAsync is enabled by default now.
*
*/
- (void)transitionLayoutWithSizeRange:(ASSizeRange)constrainedSize
animated:(BOOL)animated
shouldMeasureAsync:(BOOL)shouldMeasureAsync
measurementCompletion:(nullable void(^)())completion ASDISPLAYNODE_DEPRECATED;
/**
* @abstract Invalidates the current layout and begins a relayout of the node with the current `constrainedSize`. Must be called on main thread.
*
* @discussion It is called right after the measurement and before -animateLayoutTransition:.
*
* @param animated Animation is optional, but will still proceed through your `animateLayoutTransition` implementation with `isAnimated == NO`.
* @param shouldMeasureAsync Measure the layout asynchronously.
* @param measurementCompletion Optional completion block called only if a new layout is calculated.
*
* @see animateLayoutTransition:
*
* @deprecated Deprecated in version 2.0: Use transitionLayoutAnimated:measurementCompletion:
* shouldMeasureAsync is enabled by default now.
*
*/
- (void)transitionLayoutWithAnimation:(BOOL)animated
shouldMeasureAsync:(BOOL)shouldMeasureAsync
measurementCompletion:(nullable void(^)())completion ASDISPLAYNODE_DEPRECATED;
/**
* @abstract Cancels all performing layout transitions. Can be called on any thread.
*
* @deprecated Deprecated in version 2.0: Use cancelLayoutTransition
*/
- (void)cancelLayoutTransitionsInProgress ASDISPLAYNODE_DEPRECATED;
- (void)reclaimMemory ASDISPLAYNODE_DEPRECATED; - (void)reclaimMemory ASDISPLAYNODE_DEPRECATED;
- (void)recursivelyReclaimMemory ASDISPLAYNODE_DEPRECATED; - (void)recursivelyReclaimMemory ASDISPLAYNODE_DEPRECATED;
@property (nonatomic, assign) BOOL placeholderFadesOut ASDISPLAYNODE_DEPRECATED; @property (nonatomic, assign) BOOL placeholderFadesOut ASDISPLAYNODE_DEPRECATED;

View File

@@ -646,7 +646,7 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
return _calculatedLayout ? : [ASLayout layoutWithLayoutableObject:self constrainedSizeRange:constrainedSize size:CGSizeZero]; return _calculatedLayout ? : [ASLayout layoutWithLayoutableObject:self constrainedSizeRange:constrainedSize size:CGSizeZero];
} }
[self cancelLayoutTransitionsInProgress]; [self cancelLayoutTransition];
ASLayout *previousLayout = _calculatedLayout; ASLayout *previousLayout = _calculatedLayout;
ASLayout *newLayout = [self calculateLayoutThatFits:constrainedSize]; ASLayout *newLayout = [self calculateLayoutThatFits:constrainedSize];
@@ -701,9 +701,7 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
#pragma mark - Layout Transition #pragma mark - Layout Transition
- (void)transitionLayoutWithAnimation:(BOOL)animated - (void)transitionLayoutAnimated:(BOOL)animated measurementCompletion:(void (^)())completion
shouldMeasureAsync:(BOOL)shouldMeasureAsync
measurementCompletion:(void(^)())completion
{ {
if (_calculatedLayout == nil) { if (_calculatedLayout == nil) {
// constrainedSizeRange returns a struct and is invalid to call on nil. // constrainedSizeRange returns a struct and is invalid to call on nil.
@@ -714,14 +712,12 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
[self invalidateCalculatedLayout]; [self invalidateCalculatedLayout];
[self transitionLayoutWithSizeRange:_calculatedLayout.constrainedSizeRange [self transitionLayoutWithSizeRange:_calculatedLayout.constrainedSizeRange
animated:animated animated:animated
shouldMeasureAsync:shouldMeasureAsync
measurementCompletion:completion]; measurementCompletion:completion];
} }
- (void)transitionLayoutWithSizeRange:(ASSizeRange)constrainedSize - (void)transitionLayoutWithSizeRange:(ASSizeRange)constrainedSize
animated:(BOOL)animated animated:(BOOL)animated
shouldMeasureAsync:(BOOL)shouldMeasureAsync measurementCompletion:(void (^)())completion
measurementCompletion:(void(^)())completion
{ {
ASDisplayNodeAssertMainThread(); ASDisplayNodeAssertMainThread();
if (! [self shouldMeasureWithSizeRange:constrainedSize]) { if (! [self shouldMeasureWithSizeRange:constrainedSize]) {
@@ -741,7 +737,7 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
node.pendingTransitionID = transitionID; node.pendingTransitionID = transitionID;
}); });
void (^transitionBlock)() = ^{ ASPerformBlockOnBackgroundThread(^{
if ([self _shouldAbortTransitionWithID:transitionID]) { if ([self _shouldAbortTransitionWithID:transitionID]) {
return; return;
} }
@@ -803,12 +799,10 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
// Kick off animating the layout transition // Kick off animating the layout transition
[self animateLayoutTransition:_pendingLayoutTransitionContext]; [self animateLayoutTransition:_pendingLayoutTransitionContext];
}); });
}; });
ASPerformBlockOnBackgroundThread(transitionBlock);
} }
- (void)cancelLayoutTransitionsInProgress - (void)cancelLayoutTransition
{ {
ASDN::MutexLocker l(__instanceLock__); ASDN::MutexLocker l(__instanceLock__);
if ([self _isTransitionInProgress]) { if ([self _isTransitionInProgress]) {
@@ -861,7 +855,7 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
return (!_transitionInProgress || _transitionID != transitionID); return (!_transitionInProgress || _transitionID != transitionID);
} }
#pragma mark - Layout Transition API / ASDisplayNode (Beta) #pragma mark Layout Transition API
/* /*
* Hook for subclasse to perform an animation based on the given ASContextTransitioning. By default this just layouts * Hook for subclasse to perform an animation based on the given ASContextTransitioning. By default this just layouts
@@ -882,7 +876,7 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
[_pendingLayoutTransition applySubnodeRemovals]; [_pendingLayoutTransition applySubnodeRemovals];
} }
#pragma mark - _ASTransitionContextCompletionDelegate #pragma mark _ASTransitionContextCompletionDelegate
/* /*
* After completeTransition: is called on the ASContextTransitioning object in animateLayoutTransition: this * After completeTransition: is called on the ASContextTransitioning object in animateLayoutTransition: this
@@ -3172,6 +3166,26 @@ static const char *ASDisplayNodeAssociatedNodeKey = "ASAssociatedNode";
@implementation ASDisplayNode (Deprecated) @implementation ASDisplayNode (Deprecated)
- (void)transitionLayoutWithAnimation:(BOOL)animated
shouldMeasureAsync:(BOOL)shouldMeasureAsync
measurementCompletion:(void(^)())completion
{
[self transitionLayoutAnimated:animated measurementCompletion:completion];
}
- (void)transitionLayoutWithSizeRange:(ASSizeRange)constrainedSize
animated:(BOOL)animated
shouldMeasureAsync:(BOOL)shouldMeasureAsync
measurementCompletion:(void(^)())completion
{
[self transitionLayoutWithSizeRange:constrainedSize animated:animated measurementCompletion:completion];
}
- (void)cancelLayoutTransitionsInProgress
{
[self cancelLayoutTransition];
}
- (void)setPlaceholderFadesOut:(BOOL)placeholderFadesOut - (void)setPlaceholderFadesOut:(BOOL)placeholderFadesOut
{ {
self.placeholderFadeDuration = placeholderFadesOut ? 0.1 : 0.0; self.placeholderFadeDuration = placeholderFadesOut ? 0.1 : 0.0;

View File

@@ -11,7 +11,7 @@
// //
#import "_ASTransitionContext.h" #import "_ASTransitionContext.h"
#import "ASDisplayNode.h"
#import "ASLayout.h" #import "ASLayout.h"

View File

@@ -199,7 +199,7 @@
node.layoutState = @2; node.layoutState = @2;
[node invalidateCalculatedLayout]; [node invalidateCalculatedLayout];
[node transitionLayoutWithAnimation:YES shouldMeasureAsync:YES measurementCompletion:^{ [node transitionLayoutAnimated:YES measurementCompletion:^{
// Push this to the next runloop to let async insertion / removing of nodes finished before checking // Push this to the next runloop to let async insertion / removing of nodes finished before checking
dispatch_async(dispatch_get_main_queue(), ^{ dispatch_async(dispatch_get_main_queue(), ^{
XCTAssertEqual(node.subnodes[0], node2); XCTAssertEqual(node.subnodes[0], node2);