[ASDisplayNode] Notify rasterized subnodes that render pass has completed (#532)

* Notify rasterized subsides that render pass has completed

* Traverse entire subnode tree notifying all subnodes

* Add entry in changelog

* Retrieve rasterizesSubtree flag while holding instance lock

* Balance display delegate calls for rasterized subnodes
This commit is contained in:
Eric Scheers 2017-09-07 22:05:30 +02:00 committed by Huy Nguyen
parent 4ba6f451f6
commit 0bd18c8522
3 changed files with 65 additions and 0 deletions

View File

@ -16,6 +16,7 @@
- Table and collection views to consider content inset when calculating (default) element size range [Huy Nguyen](https://github.com/nguyenhuy) [#525](https://github.com/TextureGroup/Texture/pull/525)
- [ASEditableTextNode] added -editableTextNodeShouldBeginEditing to ASEditableTextNodeDelegate to mirror the corresponding method from UITextViewDelegate. [Yan S.](https://github.com/yans) [#535](https://github.com/TextureGroup/Texture/pull/535)
- [Breaking] Remove APIs that have been deprecated since 2.0 and/or for at least 6 months [Huy Nguyen](https://github.com/nguyenhuy) [#529](https://github.com/TextureGroup/Texture/pull/529)
- [ASDisplayNode] Ensure `-displayWillStartAsynchronously:` and `-displayDidFinish` are invoked on rasterized subnodes. [Eric Scheers](https://github.com/smeis) [#532](https://github.com/TextureGroup/Texture/pull/532)
##2.4
- Fix an issue where inserting/deleting sections could lead to inconsistent supplementary element behavior. [Adlai Holler](https://github.com/Adlai-Holler)

View File

@ -23,6 +23,8 @@
#import <AsyncDisplayKit/ASDisplayNode+FrameworkSubclasses.h>
#import <AsyncDisplayKit/ASInternalHelpers.h>
#import <AsyncDisplayKit/ASSignpost.h>
#import <AsyncDisplayKit/ASDisplayNodeExtras.h>
@interface ASDisplayNode () <_ASDisplayLayerDelegate>
@end
@ -302,6 +304,7 @@
}
CALayer *layer = _layer;
BOOL rasterizesSubtree = _flags.rasterizesSubtree;
__instanceLock__.unlock();
@ -347,11 +350,23 @@
layer.contents = (id)image.CGImage;
}
[self didDisplayAsyncLayer:self.asyncLayer];
if (rasterizesSubtree) {
ASDisplayNodePerformBlockOnEverySubnode(self, NO, ^(ASDisplayNode * _Nonnull node) {
[node didDisplayAsyncLayer:node.asyncLayer];
});
}
}
};
// Call willDisplay immediately in either case
[self willDisplayAsyncLayer:self.asyncLayer asynchronously:asynchronously];
if (rasterizesSubtree) {
ASDisplayNodePerformBlockOnEverySubnode(self, NO, ^(ASDisplayNode * _Nonnull node) {
[node willDisplayAsyncLayer:node.asyncLayer asynchronously:asynchronously];
});
}
if (asynchronously) {
// Async rendering operations are contained by a transaction, which allows them to proceed and concurrently

View File

@ -110,6 +110,10 @@ for (ASDisplayNode *n in @[ nodes ]) {\
@property (nonatomic) BOOL hasPreloaded;
@property (nonatomic) BOOL preloadStateChangedToYES;
@property (nonatomic) BOOL preloadStateChangedToNO;
@property (nonatomic, assign) NSUInteger displayWillStartCount;
@property (nonatomic, assign) NSUInteger didDisplayCount;
@end
@interface ASTestResponderNode : ASTestDisplayNode
@ -154,6 +158,18 @@ for (ASDisplayNode *n in @[ nodes ]) {\
}
}
- (void)displayDidFinish
{
[super displayDidFinish];
_didDisplayCount++;
}
- (void)displayWillStartAsynchronously:(BOOL)asynchronously
{
[super displayWillStartAsynchronously:asynchronously];
_displayWillStartCount++;
}
@end
@interface UIDisplayNodeTestView : UIView
@ -2018,6 +2034,39 @@ static bool stringContainsPointer(NSString *description, id p) {
XCTAssertThrows([rasterizedSupernode addSubnode:subnode]);
}
- (void)testThatSubnodesGetDisplayUpdatesIfRasterized
{
ASTestDisplayNode *supernode = [[ASTestDisplayNode alloc] init];
supernode.frame = CGRectMake(0.0, 0.0, 100.0, 100.0);
[supernode enableSubtreeRasterization];
ASTestDisplayNode *subnode = [[ASTestDisplayNode alloc] init];
ASTestDisplayNode *subSubnode = [[ASTestDisplayNode alloc] init];
ASSetDebugNames(supernode, subnode);
UIWindow *window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
[subnode addSubnode:subSubnode];
[supernode addSubnode:subnode];
[window addSubnode:supernode];
[window makeKeyAndVisible];
XCTAssertTrue(ASDisplayNodeRunRunLoopUntilBlockIsTrue(^BOOL{
return (subnode.didDisplayCount == 1);
}));
XCTAssertTrue(ASDisplayNodeRunRunLoopUntilBlockIsTrue(^BOOL{
return (subSubnode.didDisplayCount == 1);
}));
XCTAssertTrue(ASDisplayNodeRunRunLoopUntilBlockIsTrue(^BOOL{
return (subnode.displayWillStartCount == 1);
}));
XCTAssertTrue(ASDisplayNodeRunRunLoopUntilBlockIsTrue(^BOOL{
return (subSubnode.displayWillStartCount == 1);
}));
}
// Underlying issue for: https://github.com/facebook/AsyncDisplayKit/issues/2011
- (void)testThatLayerBackedSubnodesAreMarkedInvisibleBeforeDeallocWhenSupernodesViewIsRemovedFromHierarchyWhileBeingRetained
{