mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2026-03-06 08:20:45 +00:00
@@ -63,7 +63,7 @@
|
||||
/**
|
||||
* @abstract Whether the view or layer of this display node is currently in a window
|
||||
*/
|
||||
@property (nonatomic, readonly, assign, getter=isInWindow) BOOL inWindow;
|
||||
@property (nonatomic, readonly, assign, getter=isInHierarchy) BOOL inHierarchy;
|
||||
|
||||
|
||||
/** @name View Lifecycle */
|
||||
|
||||
@@ -74,7 +74,7 @@
|
||||
|
||||
|
||||
/**
|
||||
* @abstract Returns whether the view is synchronous.
|
||||
* @abstract Returns whether the node is synchronous.
|
||||
*
|
||||
* @return NO if the node wraps a _ASDisplayView, YES otherwise.
|
||||
*/
|
||||
@@ -98,7 +98,7 @@
|
||||
/**
|
||||
* @abstract Returns whether a node's backing view or layer is loaded.
|
||||
*
|
||||
* @return YES if a view is loaded, or if isLayerBacked is YES and layer is not nil; NO otherwise.
|
||||
* @return YES if a view is loaded, or if layerBacked is YES and layer is not nil; NO otherwise.
|
||||
*/
|
||||
@property (atomic, readonly, assign, getter=isNodeLoaded) BOOL nodeLoaded;
|
||||
|
||||
@@ -319,31 +319,31 @@
|
||||
* progress.
|
||||
*
|
||||
* Defaults to NO. Does not control display for any child or descendant nodes; for that, use
|
||||
* -recursiveSetPreventOrCancelDisplay:.
|
||||
* -recursivelySetDisplaySuspended:.
|
||||
*
|
||||
* If a setNeedsDisplay occurs while preventOrCancelDisplay is YES, and preventOrCancelDisplay is set to NO, then the
|
||||
* If a setNeedsDisplay occurs while displaySuspended is YES, and displaySuspended is set to NO, then the
|
||||
* layer will be automatically displayed.
|
||||
*/
|
||||
@property (nonatomic, assign) BOOL preventOrCancelDisplay;
|
||||
@property (nonatomic, assign) BOOL displaySuspended;
|
||||
|
||||
/**
|
||||
* @abstract Prevent the node and its descendants' layer from displaying.
|
||||
*
|
||||
* @param flag YES if display should be prevented or cancelled; NO otherwise.
|
||||
*
|
||||
* @see preventOrCancelDisplay
|
||||
* @see displaySuspended
|
||||
*/
|
||||
- (void)recursiveSetPreventOrCancelDisplay:(BOOL)flag;
|
||||
- (void)recursivelySetDisplaySuspended:(BOOL)flag;
|
||||
|
||||
/**
|
||||
* @abstract Calls -reclaimMemory on the receiver and its subnode hierarchy.
|
||||
*
|
||||
* @discussion Clears backing stores and other memory-intensive intermediates.
|
||||
* If the node is removed from a visible hierarchy and then re-added, it will automatically trigger a new asynchronous display,
|
||||
* as long as preventOrCancelDisplay is not set.
|
||||
* as long as displaySuspended is not set.
|
||||
* If the node remains in the hierarchy throughout, -setNeedsDisplay is required to trigger a new asynchronous display.
|
||||
*
|
||||
* @see preventOrCancelDisplay and setNeedsDisplay
|
||||
* @see displaySuspended and setNeedsDisplay
|
||||
*/
|
||||
|
||||
- (void)recursivelyReclaimMemory;
|
||||
|
||||
@@ -103,22 +103,19 @@ void ASDisplayNodePerformBlockOnMainThread(void (^block)())
|
||||
|
||||
#pragma mark - Lifecycle
|
||||
|
||||
// Avoid recursive loops if a subclass implements an init method that calls -initWith*Class:
|
||||
- (void)_initializeInstance
|
||||
{
|
||||
_contentsScaleForDisplay = ASDisplayNodeScreenScale();
|
||||
|
||||
_displaySentinel = [[ASSentinel alloc] init];
|
||||
|
||||
_flags.inWindow = NO;
|
||||
_flags.isInHierarchy = NO;
|
||||
_flags.displaysAsynchronously = YES;
|
||||
|
||||
// As an optimization, it may be worth a caching system that performs these checks once per class in +initialize (see above).
|
||||
_flags.implementsDisplay = [[self class] respondsToSelector:@selector(drawRect:withParameters:isCancelled:isRasterizing:)] || [self.class respondsToSelector:@selector(displayWithParameters:isCancelled:)];
|
||||
|
||||
_flags.hasClassDisplay = ([[self class] respondsToSelector:@selector(displayWithParameters:isCancelled:)] ? 1 : 0);
|
||||
_flags.hasWillDisplayAsyncLayer = ([self respondsToSelector:@selector(willDisplayAsyncLayer:)] ? 1 : 0);
|
||||
_flags.hasDrawParametersForAsyncLayer = ([self respondsToSelector:@selector(drawParametersForAsyncLayer:)] ? 1 : 0);
|
||||
_flags.implementsDrawRect = ([[self class] respondsToSelector:@selector(drawRect:withParameters:isCancelled:isRasterizing:)] ? 1 : 0);
|
||||
_flags.implementsImageDisplay = ([[self class] respondsToSelector:@selector(displayWithParameters:isCancelled:)] ? 1 : 0);
|
||||
_flags.implementsDrawParameters = ([self respondsToSelector:@selector(drawParametersForAsyncLayer:)] ? 1 : 0);
|
||||
}
|
||||
|
||||
- (id)init
|
||||
@@ -140,7 +137,7 @@ void ASDisplayNodePerformBlockOnMainThread(void (^block)())
|
||||
|
||||
[self _initializeInstance];
|
||||
_viewClass = viewClass;
|
||||
_flags.isSynchronous = ![viewClass isSubclassOfClass:[_ASDisplayView class]];
|
||||
_flags.synchronous = ![viewClass isSubclassOfClass:[_ASDisplayView class]];
|
||||
|
||||
return self;
|
||||
}
|
||||
@@ -154,8 +151,8 @@ void ASDisplayNodePerformBlockOnMainThread(void (^block)())
|
||||
|
||||
[self _initializeInstance];
|
||||
_layerClass = layerClass;
|
||||
_flags.isSynchronous = ![layerClass isSubclassOfClass:[_ASDisplayLayer class]];
|
||||
_flags.isLayerBacked = YES;
|
||||
_flags.synchronous = ![layerClass isSubclassOfClass:[_ASDisplayLayer class]];
|
||||
_flags.layerBacked = YES;
|
||||
|
||||
return self;
|
||||
}
|
||||
@@ -178,7 +175,7 @@ void ASDisplayNodePerformBlockOnMainThread(void (^block)())
|
||||
|
||||
_view = nil;
|
||||
_subnodes = nil;
|
||||
if (_flags.isLayerBacked)
|
||||
if (_flags.layerBacked)
|
||||
_layer.delegate = nil;
|
||||
_layer = nil;
|
||||
|
||||
@@ -277,8 +274,8 @@ void ASDisplayNodePerformBlockOnMainThread(void (^block)())
|
||||
|
||||
- (UIView *)view
|
||||
{
|
||||
ASDisplayNodeAssert(!_flags.isLayerBacked, @"Call to -view undefined on layer-backed nodes");
|
||||
if (_flags.isLayerBacked) {
|
||||
ASDisplayNodeAssert(!_flags.layerBacked, @"Call to -view undefined on layer-backed nodes");
|
||||
if (_flags.layerBacked) {
|
||||
return nil;
|
||||
}
|
||||
if (!_view) {
|
||||
@@ -293,7 +290,7 @@ void ASDisplayNodePerformBlockOnMainThread(void (^block)())
|
||||
if (!_layer) {
|
||||
ASDisplayNodeAssertMainThread();
|
||||
|
||||
if (!_flags.isLayerBacked) {
|
||||
if (!_flags.layerBacked) {
|
||||
return self.view.layer;
|
||||
}
|
||||
[self _loadViewOrLayerIsLayerBacked:YES];
|
||||
@@ -304,10 +301,10 @@ void ASDisplayNodePerformBlockOnMainThread(void (^block)())
|
||||
// Returns nil if our view is not an _ASDisplayView, but will create it if necessary.
|
||||
- (_ASDisplayView *)ensureAsyncView
|
||||
{
|
||||
return _flags.isSynchronous ? nil:(_ASDisplayView *)self.view;
|
||||
return _flags.synchronous ? nil : (_ASDisplayView *)self.view;
|
||||
}
|
||||
|
||||
// Returns nil if the layer is not an _ASDisplayLayer; will not create the view if nil
|
||||
// Returns nil if the layer is not an _ASDisplayLayer; will not create the layer if nil.
|
||||
- (_ASDisplayLayer *)asyncLayer
|
||||
{
|
||||
ASDN::MutexLocker l(_propertyLock);
|
||||
@@ -317,17 +314,17 @@ void ASDisplayNodePerformBlockOnMainThread(void (^block)())
|
||||
- (BOOL)isNodeLoaded
|
||||
{
|
||||
ASDN::MutexLocker l(_propertyLock);
|
||||
return (_view != nil || (_flags.isLayerBacked && _layer != nil));
|
||||
return (_view != nil || (_flags.layerBacked && _layer != nil));
|
||||
}
|
||||
|
||||
- (BOOL)isSynchronous
|
||||
{
|
||||
return _flags.isSynchronous;
|
||||
return _flags.synchronous;
|
||||
}
|
||||
|
||||
- (void)setSynchronous:(BOOL)flag
|
||||
{
|
||||
_flags.isSynchronous = flag;
|
||||
_flags.synchronous = flag;
|
||||
}
|
||||
|
||||
- (void)setLayerBacked:(BOOL)isLayerBacked
|
||||
@@ -336,15 +333,15 @@ void ASDisplayNodePerformBlockOnMainThread(void (^block)())
|
||||
|
||||
ASDN::MutexLocker l(_propertyLock);
|
||||
ASDisplayNodeAssert(!_view && !_layer, @"Cannot change isLayerBacked after layer or view has loaded");
|
||||
if (isLayerBacked != _flags.isLayerBacked && !_view && !_layer) {
|
||||
_flags.isLayerBacked = isLayerBacked;
|
||||
if (isLayerBacked != _flags.layerBacked && !_view && !_layer) {
|
||||
_flags.layerBacked = isLayerBacked;
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)isLayerBacked
|
||||
{
|
||||
ASDN::MutexLocker l(_propertyLock);
|
||||
return _flags.isLayerBacked;
|
||||
return _flags.layerBacked;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
@@ -360,10 +357,10 @@ void ASDisplayNodePerformBlockOnMainThread(void (^block)())
|
||||
// - we haven't already
|
||||
// - the width is different from the last time
|
||||
// - the height is different from the last time
|
||||
if (!_flags.sizeCalculated || !CGSizeEqualToSize(constrainedSize, _constrainedSize)) {
|
||||
if (!_flags.isMeasured || !CGSizeEqualToSize(constrainedSize, _constrainedSize)) {
|
||||
_size = [self calculateSizeThatFits:constrainedSize];
|
||||
_constrainedSize = constrainedSize;
|
||||
_flags.sizeCalculated = YES;
|
||||
_flags.isMeasured = YES;
|
||||
}
|
||||
|
||||
ASDisplayNodeAssertTrue(_size.width >= 0.0);
|
||||
@@ -387,7 +384,7 @@ void ASDisplayNodePerformBlockOnMainThread(void (^block)())
|
||||
ASDisplayNodeAssertThreadAffinity(self);
|
||||
|
||||
// Can't do this for synchronous nodes (using layers that are not _ASDisplayLayer and so we can't control display prevention/cancel)
|
||||
if (_flags.isSynchronous)
|
||||
if (_flags.synchronous)
|
||||
return;
|
||||
|
||||
ASDN::MutexLocker l(_propertyLock);
|
||||
@@ -467,7 +464,7 @@ void ASDisplayNodePerformBlockOnMainThread(void (^block)())
|
||||
- (void)displayImmediately
|
||||
{
|
||||
ASDisplayNodeAssertMainThread();
|
||||
ASDisplayNodeAssert(!_flags.isSynchronous, @"this method is designed for asynchronous mode only");
|
||||
ASDisplayNodeAssert(!_flags.synchronous, @"this method is designed for asynchronous mode only");
|
||||
|
||||
[[self asyncLayer] displayImmediately];
|
||||
}
|
||||
@@ -631,6 +628,10 @@ static inline CATransform3D _calculateTransformFromReferenceToTarget(ASDisplayNo
|
||||
|
||||
#pragma mark - _ASDisplayLayerDelegate
|
||||
|
||||
- (void)willDisplayAsyncLayer:(_ASDisplayLayer *)layer
|
||||
{
|
||||
}
|
||||
|
||||
- (void)didDisplayAsyncLayer:(_ASDisplayLayer *)layer
|
||||
{
|
||||
// Subclass hook.
|
||||
@@ -648,7 +649,7 @@ static inline CATransform3D _calculateTransformFromReferenceToTarget(ASDisplayNo
|
||||
[self __exitHierarchy];
|
||||
}
|
||||
|
||||
ASDisplayNodeAssert(_flags.isLayerBacked, @"We shouldn't get called back here if there is no layer");
|
||||
ASDisplayNodeAssert(_flags.layerBacked, @"We shouldn't get called back here if there is no layer");
|
||||
return (id<CAAction>)[NSNull null];
|
||||
}
|
||||
|
||||
@@ -657,9 +658,9 @@ static inline CATransform3D _calculateTransformFromReferenceToTarget(ASDisplayNo
|
||||
static bool disableNotificationsForMovingBetweenParents(ASDisplayNode *from, ASDisplayNode *to)
|
||||
{
|
||||
if (!from || !to) return NO;
|
||||
if (from->_flags.isSynchronous) return NO;
|
||||
if (to->_flags.isSynchronous) return NO;
|
||||
if (from->_flags.inWindow != to->_flags.inWindow) return NO;
|
||||
if (from->_flags.synchronous) return NO;
|
||||
if (to->_flags.synchronous) return NO;
|
||||
if (from->_flags.isInHierarchy != to->_flags.isInHierarchy) return NO;
|
||||
return YES;
|
||||
}
|
||||
|
||||
@@ -960,14 +961,14 @@ static NSInteger incrementIfFound(NSInteger i) {
|
||||
[_supernode _removeSubnode:self];
|
||||
|
||||
if (ASDisplayNodeThreadIsMain()) {
|
||||
if (_flags.isLayerBacked) {
|
||||
if (_flags.layerBacked) {
|
||||
[_layer removeFromSuperlayer];
|
||||
} else {
|
||||
[_view removeFromSuperview];
|
||||
}
|
||||
} else {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (_flags.isLayerBacked) {
|
||||
if (_flags.layerBacked) {
|
||||
[_layer removeFromSuperlayer];
|
||||
} else {
|
||||
[_view removeFromSuperview];
|
||||
@@ -985,7 +986,7 @@ static NSInteger incrementIfFound(NSInteger i) {
|
||||
- (void)__incrementVisibilityNotificationsDisabled
|
||||
{
|
||||
ASDN::MutexLocker l(_propertyLock);
|
||||
const size_t maxVisibilityIncrement = (1ULL<<visibilityNotificationsDisabledBits) - 1ULL;
|
||||
const size_t maxVisibilityIncrement = (1ULL<<VISIBILITY_NOTIFICATIONS_DISABLED_BITS) - 1ULL;
|
||||
ASDisplayNodeAssert(_flags.visibilityNotificationsDisabled < maxVisibilityIncrement, @"Oops, too many increments of the visibility notifications API");
|
||||
if (_flags.visibilityNotificationsDisabled < maxVisibilityIncrement)
|
||||
_flags.visibilityNotificationsDisabled++;
|
||||
@@ -1019,17 +1020,17 @@ static NSInteger incrementIfFound(NSInteger i) {
|
||||
- (void)__enterHierarchy
|
||||
{
|
||||
ASDisplayNodeAssertMainThread();
|
||||
ASDisplayNodeAssert(!_flags.isInEnterHierarchy, @"Should not cause recursive __enterHierarchy");
|
||||
if (!self.inWindow && !_flags.visibilityNotificationsDisabled && ![self __hasParentWithVisibilityNotificationsDisabled]) {
|
||||
self.inWindow = YES;
|
||||
_flags.isInEnterHierarchy = YES;
|
||||
ASDisplayNodeAssert(!_flags.isEnteringHierarchy, @"Should not cause recursive __enterHierarchy");
|
||||
if (!self.inHierarchy && !_flags.visibilityNotificationsDisabled && ![self __hasParentWithVisibilityNotificationsDisabled]) {
|
||||
self.inHierarchy = YES;
|
||||
_flags.isEnteringHierarchy = YES;
|
||||
if (self.shouldRasterizeDescendants) {
|
||||
// Nodes that are descendants of a rasterized container do not have views or layers, and so cannot receive visibility notifications directly via orderIn/orderOut CALayer actions. Manually send visibility notifications to rasterized descendants.
|
||||
[self _recursiveWillEnterHierarchy];
|
||||
} else {
|
||||
[self willEnterHierarchy];
|
||||
}
|
||||
_flags.isInEnterHierarchy = NO;
|
||||
_flags.isEnteringHierarchy = NO;
|
||||
|
||||
CALayer *layer = self.layer;
|
||||
if (!self.layer.contents) {
|
||||
@@ -1041,20 +1042,20 @@ static NSInteger incrementIfFound(NSInteger i) {
|
||||
- (void)__exitHierarchy
|
||||
{
|
||||
ASDisplayNodeAssertMainThread();
|
||||
ASDisplayNodeAssert(!_flags.isInExitHierarchy, @"Should not cause recursive __exitHierarchy");
|
||||
if (self.inWindow && !_flags.visibilityNotificationsDisabled && ![self __hasParentWithVisibilityNotificationsDisabled]) {
|
||||
self.inWindow = NO;
|
||||
ASDisplayNodeAssert(!_flags.isExitingHierarchy, @"Should not cause recursive __exitHierarchy");
|
||||
if (self.inHierarchy && !_flags.visibilityNotificationsDisabled && ![self __hasParentWithVisibilityNotificationsDisabled]) {
|
||||
self.inHierarchy = NO;
|
||||
|
||||
[self.asyncLayer cancelAsyncDisplay];
|
||||
|
||||
_flags.isInExitHierarchy = YES;
|
||||
_flags.isExitingHierarchy = YES;
|
||||
if (self.shouldRasterizeDescendants) {
|
||||
// Nodes that are descendants of a rasterized container do not have views or layers, and so cannot receive visibility notifications directly via orderIn/orderOut CALayer actions. Manually send visibility notifications to rasterized descendants.
|
||||
[self _recursiveDidExitHierarchy];
|
||||
} else {
|
||||
[self didExitHierarchy];
|
||||
}
|
||||
_flags.isInExitHierarchy = NO;
|
||||
_flags.isExitingHierarchy = NO;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1064,9 +1065,9 @@ static NSInteger incrementIfFound(NSInteger i) {
|
||||
return;
|
||||
}
|
||||
|
||||
_flags.isInEnterHierarchy = YES;
|
||||
_flags.isEnteringHierarchy = YES;
|
||||
[self willEnterHierarchy];
|
||||
_flags.isInEnterHierarchy = NO;
|
||||
_flags.isEnteringHierarchy = NO;
|
||||
|
||||
for (ASDisplayNode *subnode in self.subnodes) {
|
||||
[subnode _recursiveWillEnterHierarchy];
|
||||
@@ -1079,9 +1080,9 @@ static NSInteger incrementIfFound(NSInteger i) {
|
||||
return;
|
||||
}
|
||||
|
||||
_flags.isInExitHierarchy = YES;
|
||||
_flags.isExitingHierarchy = YES;
|
||||
[self didExitHierarchy];
|
||||
_flags.isInExitHierarchy = NO;
|
||||
_flags.isExitingHierarchy = NO;
|
||||
|
||||
for (ASDisplayNode *subnode in self.subnodes) {
|
||||
[subnode _recursiveDidExitHierarchy];
|
||||
@@ -1139,7 +1140,7 @@ static NSInteger incrementIfFound(NSInteger i) {
|
||||
{
|
||||
ASDisplayNodeAssertThreadAffinity(self);
|
||||
// This will cause -measure: to actually compute the size instead of returning the previously cached size
|
||||
_flags.sizeCalculated = NO;
|
||||
_flags.isMeasured = NO;
|
||||
}
|
||||
|
||||
- (void)didLoad
|
||||
@@ -1150,15 +1151,15 @@ static NSInteger incrementIfFound(NSInteger i) {
|
||||
- (void)willEnterHierarchy
|
||||
{
|
||||
ASDisplayNodeAssertMainThread();
|
||||
ASDisplayNodeAssert(_flags.isInEnterHierarchy, @"You should never call -willEnterHierarchy directly. Appearance is automatically managed by ASDisplayNode");
|
||||
ASDisplayNodeAssert(!_flags.isInExitHierarchy, @"ASDisplayNode inconsistency. __enterHierarchy and __exitHierarchy are mutually exclusive");
|
||||
ASDisplayNodeAssert(_flags.isEnteringHierarchy, @"You should never call -willEnterHierarchy directly. Appearance is automatically managed by ASDisplayNode");
|
||||
ASDisplayNodeAssert(!_flags.isExitingHierarchy, @"ASDisplayNode inconsistency. __enterHierarchy and __exitHierarchy are mutually exclusive");
|
||||
}
|
||||
|
||||
- (void)didExitHierarchy
|
||||
{
|
||||
ASDisplayNodeAssertMainThread();
|
||||
ASDisplayNodeAssert(_flags.isInExitHierarchy, @"You should never call -didExitHierarchy directly. Appearance is automatically managed by ASDisplayNode");
|
||||
ASDisplayNodeAssert(!_flags.isInEnterHierarchy, @"ASDisplayNode inconsistency. __enterHierarchy and __exitHierarchy are mutually exclusive");
|
||||
ASDisplayNodeAssert(_flags.isExitingHierarchy, @"You should never call -didExitHierarchy directly. Appearance is automatically managed by ASDisplayNode");
|
||||
ASDisplayNodeAssert(!_flags.isEnteringHierarchy, @"ASDisplayNode inconsistency. __enterHierarchy and __exitHierarchy are mutually exclusive");
|
||||
|
||||
[self __exitedHierarchy];
|
||||
}
|
||||
@@ -1316,7 +1317,7 @@ static NSInteger incrementIfFound(NSInteger i) {
|
||||
// for the view/layer are still valid.
|
||||
ASDN::MutexLocker l(_propertyLock);
|
||||
|
||||
if (_flags.isLayerBacked) {
|
||||
if (_flags.layerBacked) {
|
||||
[_pendingViewState applyToLayer:_layer];
|
||||
} else {
|
||||
[_pendingViewState applyToView:_view];
|
||||
@@ -1325,7 +1326,7 @@ static NSInteger incrementIfFound(NSInteger i) {
|
||||
_pendingViewState = nil;
|
||||
|
||||
// TODO: move this into real pending state
|
||||
if (_flags.preventOrCancelDisplay) {
|
||||
if (_flags.displaySuspended) {
|
||||
self.asyncLayer.displaySuspended = YES;
|
||||
}
|
||||
if (!_flags.displaysAsynchronously) {
|
||||
@@ -1358,12 +1359,12 @@ static NSInteger incrementIfFound(NSInteger i) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)recursiveSetPreventOrCancelDisplay:(BOOL)flag
|
||||
- (void)recursivelySetDisplaySuspended:(BOOL)flag
|
||||
{
|
||||
_recursiveSetPreventOrCancelDisplay(self, nil, flag);
|
||||
_recursivelySetDisplaySuspended(self, nil, flag);
|
||||
}
|
||||
|
||||
static void _recursiveSetPreventOrCancelDisplay(ASDisplayNode *node, CALayer *layer, BOOL flag)
|
||||
static void _recursivelySetDisplaySuspended(ASDisplayNode *node, CALayer *layer, BOOL flag)
|
||||
{
|
||||
// If there is no layer, but node whose its view is loaded, then we can traverse down its layer hierarchy. Otherwise we must stick to the node hierarchy to avoid loading views prematurely. Note that for nodes that haven't loaded their views, they can't possibly have subviews/sublayers, so we don't need to traverse the layer hierarchy for them.
|
||||
if (!layer && node && node.nodeLoaded) {
|
||||
@@ -1376,60 +1377,60 @@ static void _recursiveSetPreventOrCancelDisplay(ASDisplayNode *node, CALayer *la
|
||||
}
|
||||
|
||||
// Set the flag on the node. If this is a pure layer (no node) then this has no effect (plain layers don't support preventing/cancelling display).
|
||||
node.preventOrCancelDisplay = flag;
|
||||
node.displaySuspended = flag;
|
||||
|
||||
if (layer && !node.shouldRasterizeDescendants) {
|
||||
// If there is a layer, recurse down the layer hierarchy to set the flag on descendants. This will cover both layer-based and node-based children.
|
||||
for (CALayer *sublayer in layer.sublayers) {
|
||||
_recursiveSetPreventOrCancelDisplay(nil, sublayer, flag);
|
||||
_recursivelySetDisplaySuspended(nil, sublayer, flag);
|
||||
}
|
||||
} else {
|
||||
// If there is no layer (view not loaded yet) or this node rasterizes descendants (there won't be a layer tree to traverse), recurse down the subnode hierarchy to set the flag on descendants. This covers only node-based children, but for a node whose view is not loaded it can't possibly have nodeless children.
|
||||
for (ASDisplayNode *subnode in node.subnodes) {
|
||||
_recursiveSetPreventOrCancelDisplay(subnode, nil, flag);
|
||||
_recursivelySetDisplaySuspended(subnode, nil, flag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)preventOrCancelDisplay
|
||||
- (BOOL)displaySuspended
|
||||
{
|
||||
ASDisplayNodeAssertThreadAffinity(self);
|
||||
ASDN::MutexLocker l(_propertyLock);
|
||||
return _flags.preventOrCancelDisplay;
|
||||
return _flags.displaySuspended;
|
||||
}
|
||||
|
||||
- (void)setPreventOrCancelDisplay:(BOOL)flag
|
||||
- (void)setDisplaySuspended:(BOOL)flag
|
||||
{
|
||||
ASDisplayNodeAssertThreadAffinity(self);
|
||||
|
||||
// Can't do this for synchronous nodes (using layers that are not _ASDisplayLayer and so we can't control display prevention/cancel)
|
||||
if (_flags.isSynchronous)
|
||||
if (_flags.synchronous)
|
||||
return;
|
||||
|
||||
ASDN::MutexLocker l(_propertyLock);
|
||||
|
||||
if (_flags.preventOrCancelDisplay == flag)
|
||||
if (_flags.displaySuspended == flag)
|
||||
return;
|
||||
|
||||
_flags.preventOrCancelDisplay = flag;
|
||||
_flags.displaySuspended = flag;
|
||||
|
||||
self.asyncLayer.displaySuspended = flag;
|
||||
}
|
||||
|
||||
- (BOOL)isInWindow
|
||||
- (BOOL)isInHierarchy
|
||||
{
|
||||
ASDisplayNodeAssertThreadAffinity(self);
|
||||
|
||||
ASDN::MutexLocker l(_propertyLock);
|
||||
return _flags.inWindow;
|
||||
return _flags.isInHierarchy;
|
||||
}
|
||||
|
||||
- (void)setInWindow:(BOOL)inWindow
|
||||
- (void)setInHierarchy:(BOOL)inHierarchy
|
||||
{
|
||||
ASDisplayNodeAssertThreadAffinity(self);
|
||||
|
||||
ASDN::MutexLocker l(_propertyLock);
|
||||
_flags.inWindow = inWindow;
|
||||
_flags.isInHierarchy = inHierarchy;
|
||||
}
|
||||
|
||||
+ (dispatch_queue_t)asyncSizingQueue
|
||||
@@ -1507,7 +1508,7 @@ static void _recursiveSetPreventOrCancelDisplay(ASDisplayNode *node, CALayer *la
|
||||
|
||||
- (NSString *)debugDescription
|
||||
{
|
||||
NSString *notableTargetDesc = (_flags.isLayerBacked ? @" [layer]" : @" [view]");
|
||||
NSString *notableTargetDesc = (_flags.layerBacked ? @" [layer]" : @" [view]");
|
||||
if (_view && _viewClass) { // Nonstandard view is loaded
|
||||
notableTargetDesc = [NSString stringWithFormat:@" [%@ : %p]", _view.class, _view];
|
||||
} else if (_layer && _layerClass) { // Nonstandard layer is loaded
|
||||
|
||||
@@ -107,10 +107,10 @@ typedef UIImage *(^asimagenode_modification_block_t)(UIImage *image);
|
||||
*
|
||||
* @param displayCompletionBlock The block to be performed after display has
|
||||
* finished. Its `canceled` property will be YES if display was prevented or
|
||||
* canceled (via preventOrCancelDisplay); NO otherwise.
|
||||
* canceled (via displaySuspended); NO otherwise.
|
||||
*
|
||||
* @discussion displayCompletionBlock will be performed on the main-thread. If
|
||||
* `preventOrCancelDisplay` is YES, `displayCompletionBlock` is will be
|
||||
* `displaySuspended` is YES, `displayCompletionBlock` is will be
|
||||
* performed immediately and `YES` will be passed for `canceled`.
|
||||
*/
|
||||
- (void)setNeedsDisplayWithCompletion:(void (^)(BOOL canceled))displayCompletionBlock;
|
||||
|
||||
@@ -263,7 +263,7 @@
|
||||
#pragma mark -
|
||||
- (void)setNeedsDisplayWithCompletion:(void (^)(BOOL canceled))displayCompletionBlock
|
||||
{
|
||||
if (self.preventOrCancelDisplay) {
|
||||
if (self.displaySuspended) {
|
||||
if (displayCompletionBlock)
|
||||
displayCompletionBlock(YES);
|
||||
return;
|
||||
|
||||
@@ -187,7 +187,7 @@ static BOOL ASRangeIsValid(NSRange range)
|
||||
ASDisplayNodeAssertMainThread();
|
||||
ASDisplayNodeAssert(node, @"invalid argument");
|
||||
|
||||
[node recursiveSetPreventOrCancelDisplay:YES];
|
||||
[node recursivelySetDisplaySuspended:YES];
|
||||
[node.view removeFromSuperview];
|
||||
|
||||
// since this class usually manages large or infinite data sets, the working range
|
||||
@@ -526,7 +526,7 @@ static NSRange ASCalculateWorkingRange(ASRangeTuningParameters params, ASScrollD
|
||||
ASCellNode *sizedNode = _nodes[[NSIndexPath indexPathForRow:indexPath.row inSection:indexPath.section]];
|
||||
ASDisplayNodeAssert(sizedNode, @"this node should be sized but doesn't even exist");
|
||||
ASDisplayNodeAssert([sizedNode.asyncdisplaykit_indexPath isEqual:indexPath], @"this node has the wrong index path");
|
||||
[sizedNode recursiveSetPreventOrCancelDisplay:NO];
|
||||
[sizedNode recursivelySetDisplaySuspended:NO];
|
||||
return sizedNode;
|
||||
}
|
||||
|
||||
|
||||
@@ -80,9 +80,9 @@
|
||||
- (void)willMoveToWindow:(UIWindow *)newWindow
|
||||
{
|
||||
BOOL visible = newWindow != nil;
|
||||
if (visible && !_node.inWindow) {
|
||||
if (visible && !_node.inHierarchy) {
|
||||
[_node __enterHierarchy];
|
||||
} else if (!visible && _node.inWindow) {
|
||||
} else if (!visible && _node.inHierarchy) {
|
||||
[_node __exitHierarchy];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ static void __ASDisplayLayerDecrementConcurrentDisplayCount(BOOL displayIsAsync,
|
||||
|
||||
- (NSObject *)drawParameters
|
||||
{
|
||||
if (_flags.hasDrawParametersForAsyncLayer) {
|
||||
if (_flags.implementsDrawParameters) {
|
||||
return [self drawParametersForAsyncLayer:self.asyncLayer];
|
||||
}
|
||||
|
||||
@@ -197,7 +197,7 @@ static void __ASDisplayLayerDecrementConcurrentDisplayCount(BOOL displayIsAsync,
|
||||
|
||||
return image;
|
||||
};
|
||||
} else if (_flags.hasClassDisplay) {
|
||||
} else if (_flags.implementsImageDisplay) {
|
||||
// Capture drawParameters from delegate on main thread
|
||||
id drawParameters = [self drawParameters];
|
||||
|
||||
@@ -213,7 +213,7 @@ static void __ASDisplayLayerDecrementConcurrentDisplayCount(BOOL displayIsAsync,
|
||||
return result;
|
||||
};
|
||||
|
||||
} else if (_flags.implementsDisplay) {
|
||||
} else if (_flags.implementsDrawRect) {
|
||||
|
||||
CGRect bounds = self.bounds;
|
||||
if (CGRectIsEmpty(bounds)) {
|
||||
@@ -317,9 +317,7 @@ static void __ASDisplayLayerDecrementConcurrentDisplayCount(BOOL displayIsAsync,
|
||||
|
||||
if (displayBlock != NULL) {
|
||||
// Call willDisplay immediately in either case
|
||||
if (_flags.hasWillDisplayAsyncLayer) {
|
||||
[self willDisplayAsyncLayer:self.asyncLayer];
|
||||
}
|
||||
[self willDisplayAsyncLayer:self.asyncLayer];
|
||||
|
||||
if (asynchronously) {
|
||||
[transaction addOperationWithBlock:displayBlock queue:[_ASDisplayLayer displayQueue] completion:completionBlock];
|
||||
|
||||
@@ -186,7 +186,7 @@
|
||||
- (BOOL)isUserInteractionEnabled
|
||||
{
|
||||
_bridge_prologue;
|
||||
if (_flags.isLayerBacked) return NO;
|
||||
if (_flags.layerBacked) return NO;
|
||||
return _getFromViewOnly(userInteractionEnabled);
|
||||
}
|
||||
|
||||
@@ -319,28 +319,28 @@
|
||||
- (BOOL)autoresizesSubviews
|
||||
{
|
||||
_bridge_prologue;
|
||||
ASDisplayNodeAssert(!_flags.isLayerBacked, @"Danger: this property is undefined on layer-backed nodes.");
|
||||
ASDisplayNodeAssert(!_flags.layerBacked, @"Danger: this property is undefined on layer-backed nodes.");
|
||||
return _getFromViewOnly(autoresizesSubviews);
|
||||
}
|
||||
|
||||
- (void)setAutoresizesSubviews:(BOOL)flag
|
||||
{
|
||||
_bridge_prologue;
|
||||
ASDisplayNodeAssert(!_flags.isLayerBacked, @"Danger: this property is undefined on layer-backed nodes.");
|
||||
ASDisplayNodeAssert(!_flags.layerBacked, @"Danger: this property is undefined on layer-backed nodes.");
|
||||
_setToViewOnly(autoresizesSubviews, flag);
|
||||
}
|
||||
|
||||
- (UIViewAutoresizing)autoresizingMask
|
||||
{
|
||||
_bridge_prologue;
|
||||
ASDisplayNodeAssert(!_flags.isLayerBacked, @"Danger: this property is undefined on layer-backed nodes.");
|
||||
ASDisplayNodeAssert(!_flags.layerBacked, @"Danger: this property is undefined on layer-backed nodes.");
|
||||
return _getFromViewOnly(autoresizingMask);
|
||||
}
|
||||
|
||||
- (void)setAutoresizingMask:(UIViewAutoresizing)mask
|
||||
{
|
||||
_bridge_prologue;
|
||||
ASDisplayNodeAssert(!_flags.isLayerBacked, @"Danger: this property is undefined on layer-backed nodes.");
|
||||
ASDisplayNodeAssert(!_flags.layerBacked, @"Danger: this property is undefined on layer-backed nodes.");
|
||||
_setToViewOnly(autoresizingMask, mask);
|
||||
}
|
||||
|
||||
@@ -379,14 +379,14 @@
|
||||
- (UIColor *)tintColor
|
||||
{
|
||||
_bridge_prologue;
|
||||
ASDisplayNodeAssert(!_flags.isLayerBacked, @"Danger: this property is undefined on layer-backed nodes.");
|
||||
ASDisplayNodeAssert(!_flags.layerBacked, @"Danger: this property is undefined on layer-backed nodes.");
|
||||
return _getFromViewOnly(tintColor);
|
||||
}
|
||||
|
||||
- (void)setTintColor:(UIColor *)color
|
||||
{
|
||||
_bridge_prologue;
|
||||
ASDisplayNodeAssert(!_flags.isLayerBacked, @"Danger: this property is undefined on layer-backed nodes.");
|
||||
ASDisplayNodeAssert(!_flags.layerBacked, @"Danger: this property is undefined on layer-backed nodes.");
|
||||
_setToViewOnly(tintColor, color);
|
||||
}
|
||||
|
||||
|
||||
@@ -25,14 +25,15 @@ void ASDisplayNodePerformBlockOnMainThread(void (^block)());
|
||||
@class _ASPendingState;
|
||||
|
||||
// Allow 2^n increments of begin disabling hierarchy notifications
|
||||
#define visibilityNotificationsDisabledBits 4
|
||||
#define VISIBILITY_NOTIFICATIONS_DISABLED_BITS 4
|
||||
|
||||
#define TIME_DISPLAYNODE_OPS (DEBUG || PROFILE)
|
||||
|
||||
@interface ASDisplayNode () <_ASDisplayLayerDelegate>
|
||||
{
|
||||
@protected
|
||||
ASDN::RecursiveMutex _propertyLock; // Protects access to the _view, _pendingViewState, _subnodes, _supernode, _renderingSubnodes, and other properties which are accessed from multiple threads.
|
||||
// Protects access to _view, _layer, _pendingViewState, _subnodes, _supernode, and other properties which are accessed from multiple threads.
|
||||
ASDN::RecursiveMutex _propertyLock;
|
||||
|
||||
ASDisplayNode * __weak _supernode;
|
||||
|
||||
@@ -55,20 +56,24 @@ void ASDisplayNodePerformBlockOnMainThread(void (^block)());
|
||||
_ASPendingState *_pendingViewState;
|
||||
|
||||
struct {
|
||||
unsigned implementsDisplay:1;
|
||||
unsigned isSynchronous:1;
|
||||
unsigned isLayerBacked:1;
|
||||
unsigned sizeCalculated:1;
|
||||
unsigned preventOrCancelDisplay:1;
|
||||
// public properties
|
||||
unsigned synchronous:1;
|
||||
unsigned layerBacked:1;
|
||||
unsigned displaysAsynchronously:1;
|
||||
unsigned shouldRasterizeDescendants:1;
|
||||
unsigned visibilityNotificationsDisabled:visibilityNotificationsDisabledBits;
|
||||
unsigned isInEnterHierarchy:1;
|
||||
unsigned isInExitHierarchy:1;
|
||||
unsigned inWindow:1;
|
||||
unsigned hasWillDisplayAsyncLayer:1;
|
||||
unsigned hasDrawParametersForAsyncLayer:1;
|
||||
unsigned hasClassDisplay:1;
|
||||
unsigned displaySuspended:1;
|
||||
|
||||
// whether custom drawing is enabled
|
||||
unsigned implementsDrawRect:1;
|
||||
unsigned implementsImageDisplay:1;
|
||||
unsigned implementsDrawParameters:1;
|
||||
|
||||
// internal state
|
||||
unsigned isMeasured:1;
|
||||
unsigned isEnteringHierarchy:1;
|
||||
unsigned isExitingHierarchy:1;
|
||||
unsigned isInHierarchy:1;
|
||||
unsigned visibilityNotificationsDisabled:VISIBILITY_NOTIFICATIONS_DISABLED_BITS;
|
||||
} _flags;
|
||||
|
||||
ASDisplayNodeExtraIvars _extra;
|
||||
@@ -97,17 +102,17 @@ void ASDisplayNodePerformBlockOnMainThread(void (^block)());
|
||||
- (void)__layout;
|
||||
- (void)__setSupernode:(ASDisplayNode *)supernode;
|
||||
|
||||
// The visibility state of the node. Changed before calling willAppear, willDisappear, and didDisappear.
|
||||
@property (nonatomic, readwrite, assign, getter = isInWindow) BOOL inWindow;
|
||||
// Changed before calling willEnterHierarchy / didExitHierarchy.
|
||||
@property (nonatomic, readwrite, assign, getter = isInHierarchy) BOOL inHierarchy;
|
||||
|
||||
// Private API for helper funcitons / unit tests. Use ASDisplayNodeDisableHierarchyNotifications() to control this.
|
||||
// Private API for helper functions / unit tests. Use ASDisplayNodeDisableHierarchyNotifications() to control this.
|
||||
- (BOOL)__visibilityNotificationsDisabled;
|
||||
- (void)__incrementVisibilityNotificationsDisabled;
|
||||
- (void)__decrementVisibilityNotificationsDisabled;
|
||||
|
||||
// Call willEnterHierarchy if necessary and set inWindow = YES if visibility notifications are enabled on all of its parents
|
||||
// Call willEnterHierarchy if necessary and set inHierarchy = YES if visibility notifications are enabled on all of its parents
|
||||
- (void)__enterHierarchy;
|
||||
// Call didExitHierarchy if necessary and set inWindow = NO if visibility notifications are enabled on all of its parents
|
||||
// Call didExitHierarchy if necessary and set inHierarchy = NO if visibility notifications are enabled on all of its parents
|
||||
- (void)__exitHierarchy;
|
||||
|
||||
// Returns the ancestor node that rasterizes descendants, or nil if none.
|
||||
|
||||
@@ -139,7 +139,7 @@ static dispatch_block_t modifyMethodByAddingPrologueBlockAndReturnCleanupBlock(C
|
||||
XCTAssertEqual([_willEnterHierarchyCounts countForObject:n], 1u, @"willEnterHierarchy not called when node's view added to hierarchy");
|
||||
XCTAssertEqual([_didExitHierarchyCounts countForObject:n], 0u, @"didExitHierarchy erroneously called");
|
||||
|
||||
XCTAssertTrue(n.inWindow, @"Node should be visible");
|
||||
XCTAssertTrue(n.inHierarchy, @"Node should be visible");
|
||||
|
||||
if (isLayerBacked) {
|
||||
[n.layer removeFromSuperlayer];
|
||||
@@ -147,7 +147,7 @@ static dispatch_block_t modifyMethodByAddingPrologueBlockAndReturnCleanupBlock(C
|
||||
[n.view removeFromSuperview];
|
||||
}
|
||||
|
||||
XCTAssertFalse(n.inWindow, @"Node should be not visible");
|
||||
XCTAssertFalse(n.inHierarchy, @"Node should be not visible");
|
||||
|
||||
XCTAssertEqual([_willEnterHierarchyCounts countForObject:n], 1u, @"willEnterHierarchy not called when node's view added to hierarchy");
|
||||
XCTAssertEqual([_didExitHierarchyCounts countForObject:n], 1u, @"didExitHierarchy erroneously called");
|
||||
@@ -175,11 +175,11 @@ static dispatch_block_t modifyMethodByAddingPrologueBlockAndReturnCleanupBlock(C
|
||||
|
||||
[parent addSubnode:a];
|
||||
|
||||
XCTAssertFalse(parent.inWindow, @"Nothing should be visible");
|
||||
XCTAssertFalse(a.inWindow, @"Nothing should be visible");
|
||||
XCTAssertFalse(b.inWindow, @"Nothing should be visible");
|
||||
XCTAssertFalse(aa.inWindow, @"Nothing should be visible");
|
||||
XCTAssertFalse(ab.inWindow, @"Nothing should be visible");
|
||||
XCTAssertFalse(parent.inHierarchy, @"Nothing should be visible");
|
||||
XCTAssertFalse(a.inHierarchy, @"Nothing should be visible");
|
||||
XCTAssertFalse(b.inHierarchy, @"Nothing should be visible");
|
||||
XCTAssertFalse(aa.inHierarchy, @"Nothing should be visible");
|
||||
XCTAssertFalse(ab.inHierarchy, @"Nothing should be visible");
|
||||
|
||||
if (isLayerBacked) {
|
||||
[window.layer addSublayer:parent.layer];
|
||||
@@ -193,22 +193,22 @@ static dispatch_block_t modifyMethodByAddingPrologueBlockAndReturnCleanupBlock(C
|
||||
XCTAssertEqual([_willEnterHierarchyCounts countForObject:aa], 0u, @"Should not have appeared yet");
|
||||
XCTAssertEqual([_willEnterHierarchyCounts countForObject:ab], 0u, @"Should not have appeared yet");
|
||||
|
||||
XCTAssertTrue(parent.inWindow, @"Should be visible");
|
||||
XCTAssertTrue(a.inWindow, @"Should be visible");
|
||||
XCTAssertFalse(b.inWindow, @"Nothing should be visible");
|
||||
XCTAssertFalse(aa.inWindow, @"Nothing should be visible");
|
||||
XCTAssertFalse(ab.inWindow, @"Nothing should be visible");
|
||||
XCTAssertTrue(parent.inHierarchy, @"Should be visible");
|
||||
XCTAssertTrue(a.inHierarchy, @"Should be visible");
|
||||
XCTAssertFalse(b.inHierarchy, @"Nothing should be visible");
|
||||
XCTAssertFalse(aa.inHierarchy, @"Nothing should be visible");
|
||||
XCTAssertFalse(ab.inHierarchy, @"Nothing should be visible");
|
||||
|
||||
// Add to an already-visible node should make the node visible
|
||||
[parent addSubnode:b];
|
||||
[a insertSubnode:aa atIndex:0];
|
||||
[a insertSubnode:ab aboveSubnode:aa];
|
||||
|
||||
XCTAssertTrue(parent.inWindow, @"Should be visible");
|
||||
XCTAssertTrue(a.inWindow, @"Should be visible");
|
||||
XCTAssertTrue(b.inWindow, @"Should be visible after adding to visible parent");
|
||||
XCTAssertTrue(aa.inWindow, @"Nothing should be visible");
|
||||
XCTAssertTrue(ab.inWindow, @"Nothing should be visible");
|
||||
XCTAssertTrue(parent.inHierarchy, @"Should be visible");
|
||||
XCTAssertTrue(a.inHierarchy, @"Should be visible");
|
||||
XCTAssertTrue(b.inHierarchy, @"Should be visible after adding to visible parent");
|
||||
XCTAssertTrue(aa.inHierarchy, @"Nothing should be visible");
|
||||
XCTAssertTrue(ab.inHierarchy, @"Nothing should be visible");
|
||||
|
||||
XCTAssertEqual([_willEnterHierarchyCounts countForObject:parent], 1u, @"Should have -willEnterHierarchy called once");
|
||||
XCTAssertEqual([_willEnterHierarchyCounts countForObject:a], 1u, @"Should have -willEnterHierarchy called once");
|
||||
@@ -222,11 +222,11 @@ static dispatch_block_t modifyMethodByAddingPrologueBlockAndReturnCleanupBlock(C
|
||||
[parent.view removeFromSuperview];
|
||||
}
|
||||
|
||||
XCTAssertFalse(parent.inWindow, @"Nothing should be visible");
|
||||
XCTAssertFalse(a.inWindow, @"Nothing should be visible");
|
||||
XCTAssertFalse(b.inWindow, @"Nothing should be visible");
|
||||
XCTAssertFalse(aa.inWindow, @"Nothing should be visible");
|
||||
XCTAssertFalse(ab.inWindow, @"Nothing should be visible");
|
||||
XCTAssertFalse(parent.inHierarchy, @"Nothing should be visible");
|
||||
XCTAssertFalse(a.inHierarchy, @"Nothing should be visible");
|
||||
XCTAssertFalse(b.inHierarchy, @"Nothing should be visible");
|
||||
XCTAssertFalse(aa.inHierarchy, @"Nothing should be visible");
|
||||
XCTAssertFalse(ab.inHierarchy, @"Nothing should be visible");
|
||||
}
|
||||
|
||||
- (void)testAppearanceMethodsNoLayer
|
||||
@@ -262,36 +262,36 @@ static dispatch_block_t modifyMethodByAddingPrologueBlockAndReturnCleanupBlock(C
|
||||
[parentSynchronousNode addSubnode:layerBackedNode];
|
||||
[parentSynchronousNode addSubnode:viewBackedNode];
|
||||
|
||||
XCTAssertFalse(parentSynchronousNode.inWindow, @"Should not yet be visible");
|
||||
XCTAssertFalse(layerBackedNode.inWindow, @"Should not yet be visible");
|
||||
XCTAssertFalse(viewBackedNode.inWindow, @"Should not yet be visible");
|
||||
XCTAssertFalse(parentSynchronousNode.inHierarchy, @"Should not yet be visible");
|
||||
XCTAssertFalse(layerBackedNode.inHierarchy, @"Should not yet be visible");
|
||||
XCTAssertFalse(viewBackedNode.inHierarchy, @"Should not yet be visible");
|
||||
|
||||
[window addSubview:parentSynchronousNode.view];
|
||||
|
||||
// This is a known case that isn't supported
|
||||
XCTAssertFalse(parentSynchronousNode.inWindow, @"Synchronous views are not currently marked visible");
|
||||
XCTAssertFalse(parentSynchronousNode.inHierarchy, @"Synchronous views are not currently marked visible");
|
||||
|
||||
XCTAssertTrue(layerBackedNode.inWindow, @"Synchronous views' subviews should get marked visible");
|
||||
XCTAssertTrue(viewBackedNode.inWindow, @"Synchronous views' subviews should get marked visible");
|
||||
XCTAssertTrue(layerBackedNode.inHierarchy, @"Synchronous views' subviews should get marked visible");
|
||||
XCTAssertTrue(viewBackedNode.inHierarchy, @"Synchronous views' subviews should get marked visible");
|
||||
|
||||
// Try moving a node to/from a synchronous node in the window with the node API
|
||||
// Setup
|
||||
[layerBackedNode removeFromSupernode];
|
||||
[viewBackedNode removeFromSupernode];
|
||||
XCTAssertFalse(layerBackedNode.inWindow, @"aoeu");
|
||||
XCTAssertFalse(viewBackedNode.inWindow, @"aoeu");
|
||||
XCTAssertFalse(layerBackedNode.inHierarchy, @"aoeu");
|
||||
XCTAssertFalse(viewBackedNode.inHierarchy, @"aoeu");
|
||||
|
||||
// now move to synchronous node
|
||||
[parentSynchronousNode addSubnode:layerBackedNode];
|
||||
[parentSynchronousNode insertSubnode:viewBackedNode aboveSubnode:layerBackedNode];
|
||||
XCTAssertTrue(layerBackedNode.inWindow, @"Synchronous views' subviews should get marked visible");
|
||||
XCTAssertTrue(viewBackedNode.inWindow, @"Synchronous views' subviews should get marked visible");
|
||||
XCTAssertTrue(layerBackedNode.inHierarchy, @"Synchronous views' subviews should get marked visible");
|
||||
XCTAssertTrue(viewBackedNode.inHierarchy, @"Synchronous views' subviews should get marked visible");
|
||||
|
||||
[parentSynchronousNode.view removeFromSuperview];
|
||||
|
||||
XCTAssertFalse(parentSynchronousNode.inWindow, @"Should not have changed");
|
||||
XCTAssertFalse(layerBackedNode.inWindow, @"Should have been marked invisible when synchronous superview was removed from the window");
|
||||
XCTAssertFalse(viewBackedNode.inWindow, @"Should have been marked invisible when synchronous superview was removed from the window");
|
||||
XCTAssertFalse(parentSynchronousNode.inHierarchy, @"Should not have changed");
|
||||
XCTAssertFalse(layerBackedNode.inHierarchy, @"Should have been marked invisible when synchronous superview was removed from the window");
|
||||
XCTAssertFalse(viewBackedNode.inHierarchy, @"Should have been marked invisible when synchronous superview was removed from the window");
|
||||
|
||||
[window release];
|
||||
[parentSynchronousNode release];
|
||||
@@ -315,11 +315,11 @@ static dispatch_block_t modifyMethodByAddingPrologueBlockAndReturnCleanupBlock(C
|
||||
[parentA addSubnode:child];
|
||||
[child addSubnode:childSubnode];
|
||||
|
||||
XCTAssertFalse(parentA.inWindow, @"Should not yet be visible");
|
||||
XCTAssertFalse(parentB.inWindow, @"Should not yet be visible");
|
||||
XCTAssertFalse(child.inWindow, @"Should not yet be visible");
|
||||
XCTAssertFalse(childSubnode.inWindow, @"Should not yet be visible");
|
||||
XCTAssertFalse(childSubnode.inWindow, @"Should not yet be visible");
|
||||
XCTAssertFalse(parentA.inHierarchy, @"Should not yet be visible");
|
||||
XCTAssertFalse(parentB.inHierarchy, @"Should not yet be visible");
|
||||
XCTAssertFalse(child.inHierarchy, @"Should not yet be visible");
|
||||
XCTAssertFalse(childSubnode.inHierarchy, @"Should not yet be visible");
|
||||
XCTAssertFalse(childSubnode.inHierarchy, @"Should not yet be visible");
|
||||
|
||||
XCTAssertEqual([_willEnterHierarchyCounts countForObject:child], 0u, @"Should not have -willEnterHierarchy called");
|
||||
XCTAssertEqual([_willEnterHierarchyCounts countForObject:childSubnode], 0u, @"Should not have -willEnterHierarchy called");
|
||||
@@ -332,10 +332,10 @@ static dispatch_block_t modifyMethodByAddingPrologueBlockAndReturnCleanupBlock(C
|
||||
[window addSubview:parentB.view];
|
||||
}
|
||||
|
||||
XCTAssertTrue(parentA.inWindow, @"Should be visible after added to window");
|
||||
XCTAssertTrue(parentB.inWindow, @"Should be visible after added to window");
|
||||
XCTAssertTrue(child.inWindow, @"Should be visible after parent added to window");
|
||||
XCTAssertTrue(childSubnode.inWindow, @"Should be visible after parent added to window");
|
||||
XCTAssertTrue(parentA.inHierarchy, @"Should be visible after added to window");
|
||||
XCTAssertTrue(parentB.inHierarchy, @"Should be visible after added to window");
|
||||
XCTAssertTrue(child.inHierarchy, @"Should be visible after parent added to window");
|
||||
XCTAssertTrue(childSubnode.inHierarchy, @"Should be visible after parent added to window");
|
||||
|
||||
XCTAssertEqual([_willEnterHierarchyCounts countForObject:child], 1u, @"Should have -willEnterHierarchy called once");
|
||||
XCTAssertEqual([_willEnterHierarchyCounts countForObject:childSubnode], 1u, @"Should have -willEnterHierarchy called once");
|
||||
|
||||
@@ -149,7 +149,7 @@ for (ASDisplayNode *n in @[ nodes ]) {\
|
||||
XCTAssertEqual(3.f, node.shadowRadius, @"default shadowRadius broken %@", hasLoadedView);
|
||||
XCTAssertEqual(0.0f, node.borderWidth, @"default borderWidth broken %@", hasLoadedView);
|
||||
XCTAssertEqualObjects(rgbBlackCGColorIdPtr, (id)node.borderColor, @"default borderColor broken %@", hasLoadedView);
|
||||
XCTAssertEqual(NO, node.preventOrCancelDisplay, @"default preventOrCancelDisplay broken %@", hasLoadedView);
|
||||
XCTAssertEqual(NO, node.displaySuspended, @"default displaySuspended broken %@", hasLoadedView);
|
||||
XCTAssertEqual(YES, node.displaysAsynchronously, @"default displaysAsynchronously broken %@", hasLoadedView);
|
||||
XCTAssertEqual(NO, node.asyncdisplaykit_asyncTransactionContainer, @"default asyncdisplaykit_asyncTransactionContainer broken %@", hasLoadedView);
|
||||
XCTAssertEqualObjects(nil, node.name, @"default name broken %@", hasLoadedView);
|
||||
@@ -245,8 +245,8 @@ for (ASDisplayNode *n in @[ nodes ]) {\
|
||||
XCTAssertEqual(.5f, node.shadowRadius, @"shadowRadius broken %@", hasLoadedView);
|
||||
XCTAssertEqual(.5f, node.borderWidth, @"borderWidth broken %@", hasLoadedView);
|
||||
XCTAssertEqual([[UIColor orangeColor] CGColor], node.borderColor, @"borderColor broken %@", hasLoadedView);
|
||||
XCTAssertEqual(YES, node.preventOrCancelDisplay, @"preventOrCancelDisplay broken %@", hasLoadedView);
|
||||
XCTAssertEqual(NO, node.displaysAsynchronously, @"preventOrCancelDisplay broken %@", hasLoadedView);
|
||||
XCTAssertEqual(YES, node.displaySuspended, @"displaySuspended broken %@", hasLoadedView);
|
||||
XCTAssertEqual(NO, node.displaysAsynchronously, @"displaySuspended broken %@", hasLoadedView);
|
||||
XCTAssertEqual(YES, node.asyncdisplaykit_asyncTransactionContainer, @"asyncTransactionContainer broken %@", hasLoadedView);
|
||||
XCTAssertEqual(NO, node.userInteractionEnabled, @"userInteractionEnabled broken %@", hasLoadedView);
|
||||
XCTAssertEqual((BOOL)!isLayerBacked, node.exclusiveTouch, @"exclusiveTouch broken %@", hasLoadedView);
|
||||
@@ -298,7 +298,7 @@ for (ASDisplayNode *n in @[ nodes ]) {\
|
||||
node.shadowRadius = .5f;
|
||||
node.borderWidth = .5f;
|
||||
node.borderColor = [[UIColor orangeColor] CGColor];
|
||||
node.preventOrCancelDisplay = YES;
|
||||
node.displaySuspended = YES;
|
||||
node.displaysAsynchronously = NO;
|
||||
node.asyncdisplaykit_asyncTransactionContainer = YES;
|
||||
node.userInteractionEnabled = NO;
|
||||
|
||||
Reference in New Issue
Block a user