Address comments

This commit is contained in:
Michael Schneider
2016-11-16 10:07:58 -08:00
parent 2744998a10
commit a71a1d8519
10 changed files with 103 additions and 105 deletions

View File

@@ -120,10 +120,7 @@ static NSMutableSet *__cellClassesForVisibilityNotifications = nil; // See +init
- (void)displayNodeDidInvalidateSizeOldSize:(CGSize)oldSize - (void)displayNodeDidInvalidateSizeOldSize:(CGSize)oldSize
{ {
ASSizeRange constrainedSize = ASSizeRangeMake(CGSizeZero, CGSizeMake(CGRectGetWidth(self.bounds), CGFLOAT_MAX)); ASSizeRange constrainedSize = [_interactionDelegate constrainedSizeForNode:self];
if (_interactionDelegate != nil) {
constrainedSize = [_interactionDelegate constrainedSizeForNode:self];
}
CGSize newSize = [self layoutThatFits:constrainedSize].size; CGSize newSize = [self layoutThatFits:constrainedSize].size;
if (CGSizeEqualToSize(oldSize, newSize) == NO) { if (CGSizeEqualToSize(oldSize, newSize) == NO) {

View File

@@ -765,9 +765,7 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell";
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{ {
ASDisplayNode *node = [self nodeForItemAtIndexPath:indexPath]; return [[self nodeForItemAtIndexPath:indexPath] calculatedSize];
[node layoutIfNeeded];
return node.calculatedSize;
} }
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath - (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath

View File

@@ -256,9 +256,6 @@ extern NSInteger const ASDefaultDrawingPriority;
// TODO: coalesc: Documentation // TODO: coalesc: Documentation
- (void)invalidateSize; - (void)invalidateSize;
- (void)didInvalidateSize;
- (void)sizeToFit;
- (CGSize)sizeThatFits:(CGSize)size;
/** /**
* @abstract Asks the node to return a layout based on given size range. * @abstract Asks the node to return a layout based on given size range.
@@ -637,21 +634,21 @@ extern NSInteger const ASDefaultDrawingPriority;
@interface ASDisplayNode (UIViewBridge) @interface ASDisplayNode (UIViewBridge)
/** /**
* Marks the view as needing display. Convenience for use whether the view / layer is loaded or not. Safe to call from a background thread. * Marks the view as needing display. Convenience for use whether the view / layer is loaded or not. Safe to call
* from a background thread.
*/ */
- (void)setNeedsDisplay; - (void)setNeedsDisplay;
/** /**
* Marks the node as needing layout. Convenience for use whether the view / layer is loaded or not. Safe to call from a background thread. * Marks the node as needing layout. Convenience for use whether the view / layer is loaded or not. Safe to call from a background thread.
*
* If this node was measured, calling this method triggers an internal relayout: the calculated layout is invalidated,
* and the supernode is notified or (if this node is the root one) a full measurement pass is executed using the old constrained size.
*
* Note: ASCellNode has special behavior in that calling this method will automatically notify
* the containing ASTableView / ASCollectionView that the cell should be resized, if necessary.
*/ */
- (void)setNeedsLayout; - (void)setNeedsLayout;
/**
* Recalculate the receivers layout, if required.
*
* When this message is received, the layers super layers are traversed until a ancestor layer is found that does not require layout. Then layout is performed on the entire layer-tree beneath that ancestor.
*/
- (void)layoutIfNeeded; - (void)layoutIfNeeded;
@property (nonatomic, strong, nullable) id contents; // default=nil @property (nonatomic, strong, nullable) id contents; // default=nil

View File

@@ -713,8 +713,8 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
// Mark the node for layout in the next layout pass // Mark the node for layout in the next layout pass
[self invalidateCalculatedLayout]; [self invalidateCalculatedLayout];
if (_supernode) { ASDisplayNode *supernode = _supernode;
ASDisplayNode *supernode = _supernode; if (supernode) {
__instanceLock__.unlock(); __instanceLock__.unlock();
// Cause supernode's layout to be invalidated // Cause supernode's layout to be invalidated
// We need to release the lock to prevent a deadlock // We need to release the lock to prevent a deadlock
@@ -722,50 +722,39 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
return; return;
} }
// Calculate a new pending layout. It will be applied in the next layout pass // We are the root node and need to re-flow the layout; one of our children requested to have its size re-set.
ASLayout *layout = [self layoutThatFits:_calculatedDisplayNodeLayout->constrainedSize]; CGSize boundsSize = self.bounds.size;
if (CGSizeEqualToSize(self.bounds.size, layout.size) == NO) {
// If the size of the layout changes inform the node of this
[self displayNodeDidInvalidateSizeOldSize:self.bounds.size];
}
// Figure out constrainedSize to use
ASLayout *layout = nil;
if (_pendingDisplayNodeLayout != nullptr) {
layout = [self layoutThatFits:_pendingDisplayNodeLayout->constrainedSize];
} else {
layout = [self layoutThatFits:_calculatedDisplayNodeLayout->constrainedSize];
}
if (CGSizeEqualToSize(boundsSize, layout.size) == NO) {
// If the size of the layout changes inform our container (e.g ASTableView, ASCollectionView, ASViewController, ...)
// that we need it to change our bounds size.
[self displayNodeDidInvalidateSizeOldSize:boundsSize];
}
__instanceLock__.unlock(); __instanceLock__.unlock();
} }
// TODO: Pass in oldSize and new layout
- (void)displayNodeDidInvalidateSizeOldSize:(CGSize)size - (void)displayNodeDidInvalidateSizeOldSize:(CGSize)size
{
// The default implementation of display node changes the size of itself to the new size
CGRect oldBounds = self.bounds;
CGSize oldSize = oldBounds.size;
CGSize newSize = _calculatedDisplayNodeLayout->layout.size;
if (! CGSizeEqualToSize(oldSize, newSize)) {
self.bounds = (CGRect){ oldBounds.origin, newSize };
// Frame's origin must be preserved. Since it is computed from bounds size, anchorPoint
// and position (see frame setter in ASDisplayNode+UIViewBridge), position needs to be adjusted.
CGPoint anchorPoint = self.anchorPoint;
CGPoint oldPosition = self.position;
CGFloat xDelta = (newSize.width - oldSize.width) * anchorPoint.x;
CGFloat yDelta = (newSize.height - oldSize.height) * anchorPoint.y;
self.position = CGPointMake(oldPosition.x + xDelta, oldPosition.y + yDelta);
}
}
- (void)sizeToFit
{ {
ASDisplayNodeAssertThreadAffinity(self); ASDisplayNodeAssertThreadAffinity(self);
__instanceLock__.lock(); // The default implementation of display node changes the size of itself to the new size
[self setNeedsLayout];
CGSize maxSize = _supernode ? _supernode.bounds.size : CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX);
CGSize newSize = [self sizeThatFits:maxSize];
CGRect oldBounds = self.bounds; CGRect oldBounds = self.bounds;
CGSize oldSize = oldBounds.size; CGSize oldSize = oldBounds.size;
CGSize newSize = CGSizeZero;
if (_pendingDisplayNodeLayout != nullptr) {
newSize = _pendingDisplayNodeLayout->layout.size;
} else {
newSize = _calculatedDisplayNodeLayout->layout.size;
}
if (! CGSizeEqualToSize(oldSize, newSize)) { if (! CGSizeEqualToSize(oldSize, newSize)) {
self.bounds = (CGRect){ oldBounds.origin, newSize }; self.bounds = (CGRect){ oldBounds.origin, newSize };
@@ -778,13 +767,6 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
CGFloat yDelta = (newSize.height - oldSize.height) * anchorPoint.y; CGFloat yDelta = (newSize.height - oldSize.height) * anchorPoint.y;
self.position = CGPointMake(oldPosition.x + xDelta, oldPosition.y + yDelta); self.position = CGPointMake(oldPosition.x + xDelta, oldPosition.y + yDelta);
} }
__instanceLock__.unlock();
}
- (CGSize)sizeThatFits:(CGSize)size
{
return [self layoutThatFits:ASSizeRangeMake(CGSizeZero, size)].size;
} }
- (ASLayout *)layoutThatFits:(ASSizeRange)constrainedSize - (ASLayout *)layoutThatFits:(ASSizeRange)constrainedSize
@@ -1418,6 +1400,8 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
- (void)invalidateCalculatedLayout - (void)invalidateCalculatedLayout
{ {
ASDN::MutexLocker l(__instanceLock__);
// This will cause the next layout pass to compute a new layout instead of returning // This will cause the next layout pass to compute a new layout instead of returning
// the cached layout in case the constrained or parent size did not change // the cached layout in case the constrained or parent size did not change
_calculatedDisplayNodeLayout->invalidate(); _calculatedDisplayNodeLayout->invalidate();
@@ -1448,17 +1432,7 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
*/ */
- (void)__layoutIfNeeded - (void)__layoutIfNeeded
{ {
ASDisplayNodeAssertThreadAffinity(self); // TODO: Nothing in here yet
__instanceLock__.lock();
ASDisplayNode *supernode = _supernode;
__instanceLock__.unlock();
if ([supernode __needsLayout]) {
[supernode __layoutIfNeeded];
} else {
// Layout all subviews starting from the first node that needs layout
[self __layoutSublayers];
}
} }
- (void)__setNeedsDisplay - (void)__setNeedsDisplay
@@ -1520,18 +1494,18 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
} }
// Check if we can reuse the calculated display node layout // Check if we can reuse the calculated display node layout. We prefer the _pendingDisplayNodeLayout over the
if (_pendingDisplayNodeLayout == nullptr && // _calculatedDisplayNodeLayout though
_calculatedDisplayNodeLayout->isDirty() == NO && if (_pendingDisplayNodeLayout == nullptr) {
CGSizeEqualToSize(_calculatedDisplayNodeLayout->layout.size, bounds.size)) if (_calculatedDisplayNodeLayout->isDirty() == NO && CGSizeEqualToSize(_calculatedDisplayNodeLayout->layout.size, bounds.size)) {
{ // Reuse calculatedDisplayNodeLayout for layout pass
// Reuse calculatedDisplayNodeLayout for layout pass return;
return; }
} }
// Calcualted layout is not reusable we need to transform to a new one // calculatedDisplayNodeLayout is not reusable we need to transition to a new one
[self cancelLayoutTransition]; [self cancelLayoutTransition];
BOOL didCreateNewContext = NO; BOOL didCreateNewContext = NO;
BOOL didOverrideExistingContext = NO; BOOL didOverrideExistingContext = NO;
BOOL shouldVisualizeLayout = ASHierarchyStateIncludesVisualizeLayout(_hierarchyState); BOOL shouldVisualizeLayout = ASHierarchyStateIncludesVisualizeLayout(_hierarchyState);
@@ -1559,14 +1533,22 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
return _pendingDisplayNodeLayout; return _pendingDisplayNodeLayout;
} }
// By default use the bounds
CGSize parentSize = bounds.size; CGSize parentSize = bounds.size;
ASSizeRange constrainedSize = ASSizeRangeMake(parentSize); ASSizeRange constrainedSize = ASSizeRangeMake(parentSize);
// Checkout if constrained size of layouts can be reused // Checkout if constrained size of layouts can be reused
if (_pendingDisplayNodeLayout != nullptr) { if (_pendingDisplayNodeLayout != nullptr && CGSizeEqualToSize(_pendingDisplayNodeLayout->layout.size, bounds.size)) {
// We assume the size for the last returned layoutThatFits: layout was applied use it's constrainedSizes
constrainedSize = _pendingDisplayNodeLayout->constrainedSize; constrainedSize = _pendingDisplayNodeLayout->constrainedSize;
} else if (CGSizeEqualToSize(_calculatedDisplayNodeLayout->layout.size, CGSizeZero) == NO) { } else if (CGSizeEqualToSize(_calculatedDisplayNodeLayout->layout.size, CGSizeZero) == NO &&
CGSizeEqualToSize(_calculatedDisplayNodeLayout->layout.size, bounds.size)) {
// We assume the _calculatedDisplayNodeLayout is still valid
constrainedSize = _calculatedDisplayNodeLayout->constrainedSize; constrainedSize = _calculatedDisplayNodeLayout->constrainedSize;
} else {
// In this case neither the _pendingDisplayNodeLayout or the _calculatedDisplayNodeLayout constrained size can
// be reused, so the current bounds is used. This is usual the case if a frame was set manually that differs to
// the one returned from layoutThatFits:
} }
return std::make_shared<ASDisplayNodeLayout>( return std::make_shared<ASDisplayNodeLayout>(
@@ -1576,8 +1558,8 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
); );
}(); }();
// If the size of the new layout we wan to apply did change from the current bounds invalidate the whole tree up // If the size of the new layout to apply did change from the current bounds, invalidate the whole tree up
// so the root node can resize in case it needs to be // so the root node can handle a resizing if necessary
if (CGSizeEqualToSize(self.bounds.size, pendingLayout->layout.size) == NO) { if (CGSizeEqualToSize(self.bounds.size, pendingLayout->layout.size) == NO) {
[self invalidateSize]; [self invalidateSize];
} }
@@ -1604,6 +1586,19 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
} }
} }
- (ASSizeRange)conrainedSizeForCurrentLayout
{
ASSizeRange constrainedSize = ASSizeRangeMake(self.bounds.size);
// Checkout if constrained size of layouts can be reused
if (_pendingDisplayNodeLayout != nullptr) {
constrainedSize = _pendingDisplayNodeLayout->constrainedSize;
} else if (CGSizeEqualToSize(_calculatedDisplayNodeLayout->layout.size, CGSizeZero) == NO) {
constrainedSize = _calculatedDisplayNodeLayout->constrainedSize;
}
return constrainedSize;
}
- (void)layoutDidFinish - (void)layoutDidFinish
{ {
// Hook for subclasses // Hook for subclasses
@@ -2691,12 +2686,18 @@ void recursivelyTriggerDisplayForLayer(CALayer *layer, BOOL shouldBlock)
- (CGSize)calculatedSize - (CGSize)calculatedSize
{ {
ASDN::MutexLocker l(__instanceLock__); ASDN::MutexLocker l(__instanceLock__);
if (_pendingDisplayNodeLayout != nullptr) {
return _pendingDisplayNodeLayout->layout.size;
}
return _calculatedDisplayNodeLayout->layout.size; return _calculatedDisplayNodeLayout->layout.size;
} }
- (ASSizeRange)constrainedSizeForCalculatedLayout - (ASSizeRange)constrainedSizeForCalculatedLayout
{ {
ASDN::MutexLocker l(__instanceLock__); ASDN::MutexLocker l(__instanceLock__);
if (_pendingDisplayNodeLayout != nullptr) {
return _pendingDisplayNodeLayout->constrainedSize;
}
return _calculatedDisplayNodeLayout->constrainedSize; return _calculatedDisplayNodeLayout->constrainedSize;
} }

View File

@@ -751,7 +751,6 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{ {
ASCellNode *node = [_dataController nodeAtIndexPath:indexPath]; ASCellNode *node = [_dataController nodeAtIndexPath:indexPath];
[node layoutIfNeeded];
return node.calculatedSize.height; return node.calculatedSize.height;
} }

View File

@@ -16,6 +16,7 @@
#import "ASDisplayNode+FrameworkPrivate.h" #import "ASDisplayNode+FrameworkPrivate.h"
#import "ASDisplayNode+Subclasses.h" #import "ASDisplayNode+Subclasses.h"
#import "ASObjectDescriptionHelpers.h" #import "ASObjectDescriptionHelpers.h"
#import "ASLayout.h"
@interface _ASDisplayView () @interface _ASDisplayView ()
@property (nullable, atomic, weak, readwrite) ASDisplayNode *asyncdisplaykit_node; @property (nullable, atomic, weak, readwrite) ASDisplayNode *asyncdisplaykit_node;
@@ -205,10 +206,7 @@
- (CGSize)sizeThatFits:(CGSize)size - (CGSize)sizeThatFits:(CGSize)size
{ {
ASDisplayNode *node = _asyncdisplaykit_node; // Create strong reference to weak ivar. ASDisplayNode *node = _asyncdisplaykit_node; // Create strong reference to weak ivar.
if (node) { return node ? [node layoutThatFits:ASSizeRangeMake(size)].size : [super sizeThatFits:size];
return [node sizeThatFits:size];
}
return [super sizeThatFits:size];
} }
- (void)setNeedsDisplay - (void)setNeedsDisplay

View File

@@ -189,12 +189,13 @@ FOUNDATION_EXPORT NSString * const ASRenderingEngineDidDisplayNodesScheduledBefo
+ (void)scheduleNodeForRecursiveDisplay:(ASDisplayNode *)node; + (void)scheduleNodeForRecursiveDisplay:(ASDisplayNode *)node;
// The _ASDisplayLayer backing the node, if any. /// The _ASDisplayLayer backing the node, if any.
@property (nonatomic, readonly, strong) _ASDisplayLayer *asyncLayer; @property (nonatomic, readonly, strong) _ASDisplayLayer *asyncLayer;
// Bitmask to check which methods an object overrides. /// Bitmask to check which methods an object overrides.
@property (nonatomic, assign, readonly) ASDisplayNodeMethodOverrides methodOverrides; @property (nonatomic, assign, readonly) ASDisplayNodeMethodOverrides methodOverrides;
/// Thread safe way to access the bounds of the node
@property (nonatomic, assign) CGRect threadSafeBounds; @property (nonatomic, assign) CGRect threadSafeBounds;
@@ -202,23 +203,34 @@ FOUNDATION_EXPORT NSString * const ASRenderingEngineDidDisplayNodesScheduledBefo
- (BOOL)__shouldLoadViewOrLayer; - (BOOL)__shouldLoadViewOrLayer;
/** /**
Invoked before a call to setNeedsLayout to the underlying view * Invoked before a call to setNeedsLayout to the underlying view
*/ */
- (void)__setNeedsLayout; - (void)__setNeedsLayout;
/**
* The node's supernodes are traversed until a ancestor node is found that does not require layout. Then layout
* is performed on the entire node-tree beneath that ancestor
*/
- (void)__layoutIfNeeded; - (void)__layoutIfNeeded;
/** /**
Invoked after a call to setNeedsDisplay to the underlying view * Invoked after a call to setNeedsDisplay to the underlying view
*/ */
- (void)__setNeedsDisplay; - (void)__setNeedsDisplay;
/**
* Called from [CALayer layoutSublayers:]. Executes the layout pass for the node
*/
- (void)__layoutSublayers; - (void)__layoutSublayers;
/*
* Internal method to set the supernode
*/
- (void)__setSupernode:(ASDisplayNode *)supernode; - (void)__setSupernode:(ASDisplayNode *)supernode;
/** /**
Internal method to add / replace / insert subnode and remove from supernode without checking if * Internal method to add / replace / insert subnode and remove from supernode without checking if
node has automaticallyManagesSubnodes set to YES. * node has automaticallyManagesSubnodes set to YES.
*/ */
- (void)_addSubnode:(ASDisplayNode *)subnode; - (void)_addSubnode:(ASDisplayNode *)subnode;
- (void)_replaceSubnode:(ASDisplayNode *)oldSubnode withSubnode:(ASDisplayNode *)replacementSubnode; - (void)_replaceSubnode:(ASDisplayNode *)oldSubnode withSubnode:(ASDisplayNode *)replacementSubnode;
@@ -233,16 +245,16 @@ FOUNDATION_EXPORT NSString * const ASRenderingEngineDidDisplayNodesScheduledBefo
- (void)__incrementVisibilityNotificationsDisabled; - (void)__incrementVisibilityNotificationsDisabled;
- (void)__decrementVisibilityNotificationsDisabled; - (void)__decrementVisibilityNotificationsDisabled;
// Helper method to summarize whether or not the node run through the display process /// Helper method to summarize whether or not the node run through the display process
- (BOOL)__implementsDisplay; - (BOOL)__implementsDisplay;
// Display the node's view/layer immediately on the current thread, bypassing the background thread rendering. Will be deprecated. /// Display the node's view/layer immediately on the current thread, bypassing the background thread rendering. Will be deprecated.
- (void)displayImmediately; - (void)displayImmediately;
// Alternative initialiser for backing with a custom view class. Supports asynchronous display with _ASDisplayView subclasses. /// Alternative initialiser for backing with a custom view class. Supports asynchronous display with _ASDisplayView subclasses.
- (instancetype)initWithViewClass:(Class)viewClass; - (instancetype)initWithViewClass:(Class)viewClass;
// Alternative initialiser for backing with a custom layer class. Supports asynchronous display with _ASDisplayLayer subclasses. /// Alternative initialiser for backing with a custom layer class. Supports asynchronous display with _ASDisplayLayer subclasses.
- (instancetype)initWithLayerClass:(Class)layerClass; - (instancetype)initWithLayerClass:(Class)layerClass;
@property (nonatomic, assign) CGFloat contentsScaleForDisplay; @property (nonatomic, assign) CGFloat contentsScaleForDisplay;

View File

@@ -45,7 +45,7 @@ BOOL ASDisplayNodeRunRunLoopUntilBlockIsTrue(as_condition_block_t block)
} }
void ASDisplayNodeSizeToFitSize(ASDisplayNode *node, CGSize size) { void ASDisplayNodeSizeToFitSize(ASDisplayNode *node, CGSize size) {
CGSize sizeThatFits = [node sizeThatFits:size]; CGSize sizeThatFits = [node layoutThatFits:ASSizeRangeMake(size)].size;
node.bounds = (CGRect){.origin = CGPointZero, .size = sizeThatFits}; node.bounds = (CGRect){.origin = CGPointZero, .size = sizeThatFits};
} }
void ASDisplayNodeSizeToFitSizeRange(ASDisplayNode *node, ASSizeRange sizeRange) { void ASDisplayNodeSizeToFitSizeRange(ASDisplayNode *node, ASSizeRange sizeRange) {

View File

@@ -47,14 +47,11 @@
imageNode.style.width = ASDimensionMake(forcedImageSize.width); imageNode.style.width = ASDimensionMake(forcedImageSize.width);
imageNode.style.height = ASDimensionMake(forcedImageSize.height); imageNode.style.height = ASDimensionMake(forcedImageSize.height);
ASDisplayNodeSizeToFitSize(imageNode, forcedImageSize); ASDisplayNodeSizeToFitSize(imageNode, forcedImageSize);
[imageNode layoutIfNeeded];
ASSnapshotVerifyNode(imageNode, @"first"); ASSnapshotVerifyNode(imageNode, @"first");
imageNode.style.width = ASDimensionMake(200); imageNode.style.width = ASDimensionMake(200);
imageNode.style.height = ASDimensionMake(200); imageNode.style.height = ASDimensionMake(200);
ASDisplayNodeSizeToFitSize(imageNode, CGSizeMake(200, 200)); ASDisplayNodeSizeToFitSize(imageNode, CGSizeMake(200, 200));
[imageNode layoutIfNeeded];
ASSnapshotVerifyNode(imageNode, @"second"); ASSnapshotVerifyNode(imageNode, @"second");
XCTAssert(CGImageGetWidth((CGImageRef)imageNode.contents) == forcedImageSize.width * imageNode.contentsScale && XCTAssert(CGImageGetWidth((CGImageRef)imageNode.contents) == forcedImageSize.width * imageNode.contentsScale &&

View File

@@ -25,8 +25,7 @@
textNode.attributedText = [[NSAttributedString alloc] initWithString:@"judar" textNode.attributedText = [[NSAttributedString alloc] initWithString:@"judar"
attributes:@{NSFontAttributeName : [UIFont italicSystemFontOfSize:24]}]; attributes:@{NSFontAttributeName : [UIFont italicSystemFontOfSize:24]}];
textNode.textContainerInset = UIEdgeInsetsMake(0, 2, 0, 2); textNode.textContainerInset = UIEdgeInsetsMake(0, 2, 0, 2);
ASLayout *layout = [textNode layoutThatFits:ASSizeRangeMake(CGSizeZero, CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX))]; ASDisplayNodeSizeToFitSizeRange(textNode, ASSizeRangeMake(CGSizeZero, CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX)));
textNode.frame = CGRectMake(0, 0, layout.size.width, layout.size.height);
ASSnapshotVerifyNode(textNode, nil); ASSnapshotVerifyNode(textNode, nil);
} }