Small changes required by the coming layout debugger (#337)

* Small changes required by the layout debugger
- `ASDisplayNode` can be told to not flatten its layout immediately but later on. The unflattened layout is also stored in a separate property. It's needed for inspecting not only display nodes but also layout specs used to compute a layout tree.
- `ASLayout` can be told to always retain its sublayout elements. This is needed especially for layout specs since they are usually not retained after an ASLayout was computed.

* Update CHANGELOG

* Address comments
This commit is contained in:
Huy Nguyen 2017-06-08 10:47:50 -07:00 committed by GitHub
parent 13c467b2f4
commit 05e9bdd092
8 changed files with 87 additions and 5 deletions

View File

@ -35,3 +35,4 @@
- [Fix] Fixed a bug where ASVideoNodeDelegate error reporting callback would crash an app because of not responding to selector. [Sergey Petrachkov](https://github.com/Petrachkov) [#291](https://github.com/TextureGroup/Texture/issues/291)
- [IGListKit] Add IGListKit headers to public section of Xcode project [Michael Schneider](https://github.com/maicki)[#286](https://github.com/TextureGroup/Texture/pull/286)
- [Layout] Ensure -layout and -layoutDidFinish are called only if a node is loaded. [Huy Nguyen](https://github.com/nguyenhuy) [#285](https://github.com/TextureGroup/Texture/pull/285)
- [Layout Debugger] Small changes needed for the coming layout debugger [Huy Nguyen](https://github.com/nguyenhuy) [#337](https://github.com/TextureGroup/Texture/pull/337)

View File

@ -911,6 +911,12 @@ ASPrimitiveTraitCollectionDeprecatedImplementation
ASDisplayNodeAssertTrue(displayNodeLayout->layout.size.width >= 0.0);
ASDisplayNodeAssertTrue(displayNodeLayout->layout.size.height >= 0.0);
// Flatten the layout if it wasn't done before (@see -calculateLayoutThatFits:).
if ([ASDisplayNode shouldStoreUnflattenedLayouts]) {
_unflattenedLayout = displayNodeLayout->layout;
displayNodeLayout->layout = [_unflattenedLayout filteredNodeLayoutTree];
}
_calculatedDisplayNodeLayout = displayNodeLayout;
}

View File

@ -553,6 +553,30 @@ extern NSInteger const ASDefaultDrawingPriority;
*/
@interface ASDisplayNode (Debugging) <ASDebugNameProvider>
/**
* Set to YES to tell all ASDisplayNode instances to store their unflattened layouts.
*
* The layout can be accessed via `-unflattenedCalculatedLayout`.
*
* Flattened layouts use less memory and are faster to lookup. On the other hand, unflattened layouts are useful for debugging
* because they preserve original information.
*/
+ (void)setShouldStoreUnflattenedLayouts:(BOOL)shouldStore;
/**
* Whether or not ASDisplayNode instances should store their unflattened layouts.
*
* The layout can be accessed via `-unflattenedCalculatedLayout`.
*
* Flattened layouts use less memory and are faster to lookup. On the other hand, unflattened layouts are useful for debugging
* because they preserve original information.
*
* Defaults to NO.
*/
+ (BOOL)shouldStoreUnflattenedLayouts;
@property (nonatomic, strong, readonly, nullable) ASLayout *unflattenedCalculatedLayout;
/**
* @abstract Return a description of the node hierarchy.
*

View File

@ -82,6 +82,7 @@ NSInteger const ASDefaultDrawingPriority = ASDefaultTransactionPriority;
@synthesize threadSafeBounds = _threadSafeBounds;
static BOOL suppressesInvalidCollectionUpdateExceptions = NO;
static std::atomic_bool storesUnflattenedLayouts = ATOMIC_VAR_INIT(NO);
+ (BOOL)suppressesInvalidCollectionUpdateExceptions
{
@ -888,6 +889,8 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
_pendingDisplayNodeLayout->invalidate();
}
_unflattenedLayout = nil;
#if YOGA_TREE_CONTIGUOUS
[self invalidateCalculatedYogaLayout];
#endif
@ -1013,7 +1016,6 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
// Manually propagate the trait collection here so that any layoutSpec children of layoutSpec will get a traitCollection
{
ASDN::SumScopeTimer t(_layoutSpecTotalTime, measureLayoutSpec);
ASTraitCollectionPropagateDown(layoutElement, self.primitiveTraitCollection);
}
@ -1038,7 +1040,13 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
}
ASDisplayNodeLogEvent(self, @"computedLayout: %@", layout);
return [layout filteredNodeLayoutTree];
// Return the (original) unflattened layout if it needs to be stored. The layout will be flattened later on (@see _locked_setCalculatedDisplayNodeLayout:).
// Otherwise, flatten it right away.
if (! [ASDisplayNode shouldStoreUnflattenedLayouts]) {
layout = [layout filteredNodeLayoutTree];
}
return layout;
}
- (CGSize)calculateSizeThatFits:(CGSize)constrainedSize
@ -3286,6 +3294,22 @@ ASDISPLAYNODE_INLINE BOOL subtreeIsRasterized(ASDisplayNode *node) {
@implementation ASDisplayNode (Debugging)
+ (void)setShouldStoreUnflattenedLayouts:(BOOL)shouldStore
{
storesUnflattenedLayouts.store(shouldStore);
}
+ (BOOL)shouldStoreUnflattenedLayouts
{
return storesUnflattenedLayouts.load();
}
- (ASLayout *)unflattenedCalculatedLayout
{
ASDN::MutexLocker l(__instanceLock__);
return _unflattenedLayout;
}
- (NSString *)displayNodeRecursiveDescription
{
return [self _recursiveDescriptionHelperWithIndent:@""];

View File

@ -98,7 +98,7 @@ extern ASDisplayNode * _Nullable ASLayerToDisplayNode(CALayer * _Nullable layer)
extern ASDisplayNode * _Nullable ASViewToDisplayNode(UIView * _Nullable view) AS_WARN_UNUSED_RESULT;
/**
Given a node, returns the root of the node heirarchy (where supernode == nil)
Given a node, returns the root of the node hierarchy (where supernode == nil)
*/
extern ASDisplayNode *ASDisplayNodeUltimateParentOfNode(ASDisplayNode *node) AS_WARN_UNUSED_RESULT;

View File

@ -176,6 +176,18 @@ ASDISPLAYNODE_EXTERN_C_END
@interface ASLayout (Debugging)
/**
* Set to YES to tell all ASLayout instances to retain their sublayout elements. Defaults to NO.
* Can be overridden at instance level.
*/
+ (void)setShouldRetainSublayoutLayoutElements:(BOOL)shouldRetain;
/**
* Whether or not ASLayout instances should retain their sublayout elements.
* Can be overridden at instance level.
*/
+ (BOOL)shouldRetainSublayoutLayoutElements;
/**
* Recrusively output the description of the layout tree.
*/

View File

@ -76,6 +76,18 @@ static inline NSString * descriptionIndents(NSUInteger indents)
@dynamic frame, type;
static std::atomic_bool static_retainsSublayoutLayoutElements = ATOMIC_VAR_INIT(NO);
+ (void)setShouldRetainSublayoutLayoutElements:(BOOL)shouldRetain
{
static_retainsSublayoutLayoutElements.store(shouldRetain);
}
+ (BOOL)shouldRetainSublayoutLayoutElements
{
return static_retainsSublayoutLayoutElements.load();
}
- (instancetype)initWithLayoutElement:(id<ASLayoutElement>)layoutElement
size:(CGSize)size
position:(CGPoint)position
@ -118,7 +130,7 @@ static inline NSString * descriptionIndents(NSUInteger indents)
}
_flattened = NO;
_retainSublayoutLayoutElements = NO;
self.retainSublayoutLayoutElements = [ASLayout shouldRetainSublayoutLayoutElements];
}
return self;

View File

@ -211,6 +211,9 @@ FOUNDATION_EXPORT NSString * const ASRenderingEngineDidDisplayNodesScheduledBefo
NSString *_debugName;
#pragma mark - ASDisplayNode (Debugging)
ASLayout *_unflattenedLayout;
#if TIME_DISPLAYNODE_OPS
@public
NSTimeInterval _debugTimeToCreateView;