mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-23 06:35:51 +00:00
Remove unused methods.
`-[ASDisplayNode addSubnodeAsynchronously::]` and `-replaceSubnodeAsynchronously:::` are unused and confusingly increase AsyncDisplayKit's API surface. `-addSubnode:` and friends are thread-safe and can be used on background threads, so removing these methods does not constitute a decrease in functionality.
This commit is contained in:
@@ -221,32 +221,6 @@
|
|||||||
*/
|
*/
|
||||||
- (void)replaceSubnode:(ASDisplayNode *)subnode withSubnode:(ASDisplayNode *)replacementSubnode;
|
- (void)replaceSubnode:(ASDisplayNode *)subnode withSubnode:(ASDisplayNode *)replacementSubnode;
|
||||||
|
|
||||||
/**
|
|
||||||
* @abstract Add a subnode, but have it size asynchronously on a background queue.
|
|
||||||
*
|
|
||||||
* @param subnode The unsized subnode to insert into the view hierarchy
|
|
||||||
* @param completion The completion callback will be called on the main queue after the subnode has been inserted in
|
|
||||||
* place of the placeholder.
|
|
||||||
*
|
|
||||||
* @return A placeholder node is inserted into the hierarchy where the node will be. The placeholder can be moved around
|
|
||||||
* in the hiercharchy while the view is sizing. Once sizing is complete on the background queue, this placeholder will
|
|
||||||
* be removed and the replacement will be put at its place.
|
|
||||||
*/
|
|
||||||
- (ASDisplayNode *)addSubnodeAsynchronously:(ASDisplayNode *)subnode
|
|
||||||
completion:(void(^)(ASDisplayNode *replacement))completion;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @abstract Replace a subnode, but have it size asynchronously on a background queue.
|
|
||||||
*
|
|
||||||
* @param subnode A subnode of self.
|
|
||||||
* @param replacementSubnode A node with which to replace subnode.
|
|
||||||
* @param completion The completion callback will be called on the main queue after the replacementSubnode has replaced
|
|
||||||
* subnode.
|
|
||||||
*/
|
|
||||||
- (void)replaceSubnodeAsynchronously:(ASDisplayNode *)subnode
|
|
||||||
withNode:(ASDisplayNode *)replacementSubnode
|
|
||||||
completion:(void(^)(BOOL cancelled, ASDisplayNode *replacement, ASDisplayNode *oldSubnode))completion;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @abstract Remove this node from its supernode.
|
* @abstract Remove this node from its supernode.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1401,91 +1401,6 @@ static void _recursiveSetPreventOrCancelDisplay(ASDisplayNode *node, CALayer *la
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)replaceSubnodeAsynchronously:(ASDisplayNode *)old withNode:(ASDisplayNode *)replacement completion:(void(^)(BOOL cancelled, ASDisplayNode *replacement, ASDisplayNode *oldSubnode))completion
|
|
||||||
{
|
|
||||||
|
|
||||||
ASDisplayNodeAssert(old.supernode == self, @"Must replace something that is actually a subnode. You passed: %@", old);
|
|
||||||
ASDisplayNodeAssert(!replacement.nodeLoaded, @"Can't async size something that already has a view, since we currently have no way to convert a viewed node into a viewless one...");
|
|
||||||
|
|
||||||
// If we're already marked for replacement, cancel the pending request
|
|
||||||
ASSentinel *sentinel = [old _asyncReplaceSentinel];
|
|
||||||
uint32_t sentinelValue = [sentinel increment];
|
|
||||||
|
|
||||||
// Enqueue async sizing on our argument
|
|
||||||
[replacement _enqueueAsyncSizingWithSentinel:sentinel completion:^(ASDisplayNode *replacementCompletedNode) {
|
|
||||||
// Sizing is done; swap with our other view
|
|
||||||
// Check sentinel one more time in case it changed during sizing
|
|
||||||
if (replacementCompletedNode && sentinel.value == sentinelValue) {
|
|
||||||
if (old.supernode) {
|
|
||||||
if (old.supernode.inWindow) {
|
|
||||||
// Now wait for async display before notifying delegate that replacement is complete
|
|
||||||
|
|
||||||
// When async sizing is complete, add subnode below placeholder with 0 alpha
|
|
||||||
CGFloat replacementAlpha = replacement.alpha;
|
|
||||||
BOOL wasAsyncTransactionContainer = replacement.asyncdisplaykit_asyncTransactionContainer;
|
|
||||||
[old.supernode insertSubnode:replacement belowSubnode:old];
|
|
||||||
|
|
||||||
replacementCompletedNode.alpha = 0.0;
|
|
||||||
replacementCompletedNode.asyncdisplaykit_asyncTransactionContainer = YES;
|
|
||||||
|
|
||||||
ASDisplayNodeCAssert(replacementCompletedNode.nodeLoaded, @".layer shouldn't be the thing to load the view");
|
|
||||||
|
|
||||||
[replacement.layer.asyncdisplaykit_asyncTransaction addCompletionBlock:^(id<NSObject> unused, BOOL canceled) {
|
|
||||||
ASDisplayNodeCAssertMainThread();
|
|
||||||
|
|
||||||
canceled |= (sentinel.value != sentinelValue);
|
|
||||||
|
|
||||||
replacementCompletedNode.alpha = replacementAlpha;
|
|
||||||
replacementCompletedNode.asyncdisplaykit_asyncTransactionContainer = wasAsyncTransactionContainer;
|
|
||||||
|
|
||||||
if (!canceled) {
|
|
||||||
[old removeFromSupernode];
|
|
||||||
} else {
|
|
||||||
[replacementCompletedNode removeFromSupernode];
|
|
||||||
}
|
|
||||||
|
|
||||||
completion(canceled, replacementCompletedNode, old);
|
|
||||||
}];
|
|
||||||
} else {
|
|
||||||
// Not in window, don't wait for async display
|
|
||||||
[old.supernode replaceSubnode:old withSubnode:replacement];
|
|
||||||
completion(NO, replacementCompletedNode, old);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else { // Old has been moved no longer to be in the hierarchy
|
|
||||||
// TODO: add code to removeFromSupernode and hook UIView methods to cancel sentinel here?
|
|
||||||
@throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"Tried to replaceSubnodeAsynchronously an ASDisplayNode, but then removed it from the hierarchy... what did you mean?" userInfo:nil];
|
|
||||||
|
|
||||||
completion(NO, replacementCompletedNode, old);
|
|
||||||
}
|
|
||||||
} else { // If we were cancelled
|
|
||||||
completion(YES, nil, nil);
|
|
||||||
}
|
|
||||||
}];
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
- (ASDisplayNode *)addSubnodeAsynchronously:(ASDisplayNode *)replacement completion:(void(^)(ASDisplayNode *fullySizedSubnode))completion
|
|
||||||
{
|
|
||||||
ASDisplayNodeAssertThreadAffinity(self);
|
|
||||||
|
|
||||||
// Create a placeholder ASDisplayNode that saves this guy's place in the view hierarchy for when things return later
|
|
||||||
ASDisplayNode *placeholder = [[ASDisplayNode alloc] init];
|
|
||||||
|
|
||||||
[self addSubnode:placeholder];
|
|
||||||
[self replaceSubnodeAsynchronously:placeholder withNode:replacement completion:^(BOOL cancelled, ASDisplayNode *replacementBlock, ASDisplayNode *placeholderBlock) {
|
|
||||||
if (replacementBlock && placeholderBlock && !cancelled) {
|
|
||||||
[placeholderBlock removeFromSupernode];
|
|
||||||
completion(replacementBlock);
|
|
||||||
} else {
|
|
||||||
[placeholderBlock removeFromSupernode];
|
|
||||||
}
|
|
||||||
}];
|
|
||||||
|
|
||||||
return placeholder;
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation ASDisplayNode (Debugging)
|
@implementation ASDisplayNode (Debugging)
|
||||||
|
|||||||
@@ -914,167 +914,6 @@ static inline BOOL _CGPointEqualToPointWithEpsilon(CGPoint point1, CGPoint point
|
|||||||
[d release];
|
[d release];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)testAddSubnodeAsync
|
|
||||||
{
|
|
||||||
|
|
||||||
ASTestDisplayNode *parent = [[ASTestDisplayNode alloc] init];
|
|
||||||
|
|
||||||
__block BOOL calculateSizeCalled = NO;
|
|
||||||
__block CGSize passedInSize;
|
|
||||||
__block BOOL sizeCalculatedOnMainThread;
|
|
||||||
ASTestDisplayNode *nodeToAddAsync = [[ASTestDisplayNode alloc] init];
|
|
||||||
nodeToAddAsync.bounds = CGRectMake(100, 40, 42, 56);
|
|
||||||
nodeToAddAsync.calculateSizeBlock = ^(ASDisplayNode *n, CGSize size){
|
|
||||||
calculateSizeCalled = YES;
|
|
||||||
passedInSize = size;
|
|
||||||
sizeCalculatedOnMainThread = [NSThread isMainThread];
|
|
||||||
return CGSizeZero;
|
|
||||||
};
|
|
||||||
|
|
||||||
dispatch_suspend([ASDisplayNode asyncSizingQueue]);
|
|
||||||
|
|
||||||
__block BOOL completed = NO;
|
|
||||||
ASDisplayNode *placeholder = [parent addSubnodeAsynchronously:nodeToAddAsync completion:^(ASDisplayNode *replacement) {
|
|
||||||
completed = YES;
|
|
||||||
}];
|
|
||||||
|
|
||||||
// Check it hasn't been added yet
|
|
||||||
XCTAssertTrue(placeholder.supernode == parent, @"didn't make a placeholder");
|
|
||||||
XCTAssertTrue(nodeToAddAsync.supernode == nil, @"oops, added node too soon");
|
|
||||||
XCTAssertFalse(calculateSizeCalled, @"too soon to calculate size!");
|
|
||||||
|
|
||||||
dispatch_resume([ASDisplayNode asyncSizingQueue]);
|
|
||||||
|
|
||||||
// Let the block execute on the bg thread
|
|
||||||
XCTAssertTrue(ASDisplayNodeRunRunLoopUntilBlockIsTrue(^BOOL{ return completed; }), @"Didn't finish the test fast enough");
|
|
||||||
|
|
||||||
XCTAssertTrue(placeholder.supernode == nil, @"didn't remove the placeholder");
|
|
||||||
XCTAssertTrue(nodeToAddAsync.supernode == parent, @"oops, didn't add the node");
|
|
||||||
XCTAssertTrue(calculateSizeCalled, @"too soon to calculate size!");
|
|
||||||
XCTAssertTrue(CGSizeEqualToSize(CGSizeMake(42, 56), passedInSize), @"Should pass in initial bounds size");
|
|
||||||
XCTAssertFalse(sizeCalculatedOnMainThread, @"Should pass in initial bounds size");
|
|
||||||
|
|
||||||
[parent release];
|
|
||||||
[nodeToAddAsync release];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)testReplaceSubnodeAsync
|
|
||||||
{
|
|
||||||
ASTestDisplayNode *parent = [[ASTestDisplayNode alloc] init];
|
|
||||||
|
|
||||||
__block BOOL calculateSizeCalled = NO;
|
|
||||||
__block CGSize passedInSize;
|
|
||||||
__block BOOL sizeCalculatedOnMainThread;
|
|
||||||
ASTestDisplayNode *nodeToAddAsync = [[ASTestDisplayNode alloc] init];
|
|
||||||
nodeToAddAsync.bounds = CGRectMake(100, 40, 42, 56);
|
|
||||||
nodeToAddAsync.calculateSizeBlock = ^(ASDisplayNode *n, CGSize size){
|
|
||||||
calculateSizeCalled = YES;
|
|
||||||
passedInSize = size;
|
|
||||||
sizeCalculatedOnMainThread = [NSThread isMainThread];
|
|
||||||
return CGSizeZero;
|
|
||||||
};
|
|
||||||
|
|
||||||
ASDisplayNode *replaceMe = [[ASDisplayNode alloc] init];
|
|
||||||
[parent addSubnode:replaceMe];
|
|
||||||
|
|
||||||
dispatch_suspend([ASDisplayNode asyncSizingQueue]);
|
|
||||||
|
|
||||||
__block BOOL completed = NO;
|
|
||||||
|
|
||||||
[parent replaceSubnodeAsynchronously:replaceMe withNode:nodeToAddAsync completion:^(BOOL cancelled, ASDisplayNode *nodeToAddAsyncBlockArgument, ASDisplayNode *replaceMeBlockArgument) {
|
|
||||||
XCTAssertTrue(nodeToAddAsyncBlockArgument == nodeToAddAsync, @"Passed in wrong node for the replacing node");
|
|
||||||
XCTAssertTrue(replaceMeBlockArgument == replaceMe, @"Passed in wrong node for the replaced node");
|
|
||||||
completed = YES;
|
|
||||||
}];
|
|
||||||
|
|
||||||
// Check it hasn't been replaced yet
|
|
||||||
XCTAssertTrue(replaceMe.supernode == parent, @"removed too soon!");
|
|
||||||
XCTAssertTrue(nodeToAddAsync.supernode == nil, @"oops, added node too soon");
|
|
||||||
XCTAssertFalse(calculateSizeCalled, @"too soon to calculate size!");
|
|
||||||
|
|
||||||
dispatch_resume([ASDisplayNode asyncSizingQueue]);
|
|
||||||
|
|
||||||
// Let the block execute on the bg thread
|
|
||||||
XCTAssertTrue(ASDisplayNodeRunRunLoopUntilBlockIsTrue(^BOOL{ return completed; }), @"Didn't finish the test fast enough");
|
|
||||||
|
|
||||||
XCTAssertTrue(replaceMe.supernode == nil, @"didn't remove old node");
|
|
||||||
XCTAssertTrue(nodeToAddAsync.supernode == parent, @"oops, added node too soon");
|
|
||||||
XCTAssertTrue(calculateSizeCalled, @"too soon to calculate size!");
|
|
||||||
XCTAssertTrue(CGSizeEqualToSize(CGSizeMake(42, 56), passedInSize), @"Should pass in initial bounds size");
|
|
||||||
XCTAssertFalse(sizeCalculatedOnMainThread, @"Should pass in initial bounds size");
|
|
||||||
|
|
||||||
[parent release];
|
|
||||||
[nodeToAddAsync release];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)testCancelReplaceSubnodeAsyncByReplacingAgain
|
|
||||||
{
|
|
||||||
|
|
||||||
ASTestDisplayNode *parent = [[ASTestDisplayNode alloc] init];
|
|
||||||
|
|
||||||
dispatch_semaphore_t allowFirst = dispatch_semaphore_create(0);
|
|
||||||
ASTestDisplayNode *first = [[ASTestDisplayNode alloc] init];
|
|
||||||
first.bounds = CGRectMake(100, 40, 42, 56);
|
|
||||||
first.calculateSizeBlock = ^(ASDisplayNode *n, CGSize size){
|
|
||||||
dispatch_semaphore_wait(allowFirst, DISPATCH_TIME_FOREVER);
|
|
||||||
return CGSizeZero;
|
|
||||||
};
|
|
||||||
|
|
||||||
dispatch_semaphore_t allowSecond = dispatch_semaphore_create(0);
|
|
||||||
ASTestDisplayNode *second = [[ASTestDisplayNode alloc] init];
|
|
||||||
second.bounds = CGRectMake(100, 40, 42, 56);
|
|
||||||
second.calculateSizeBlock = ^(ASDisplayNode *n, CGSize size){
|
|
||||||
dispatch_semaphore_wait(allowSecond, DISPATCH_TIME_FOREVER);
|
|
||||||
return CGSizeMake(10, 20);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
ASDisplayNode *replaceMe = [[ASDisplayNode alloc] init];
|
|
||||||
[parent addSubnode:replaceMe];
|
|
||||||
|
|
||||||
__block BOOL firstFinished = NO;
|
|
||||||
[parent replaceSubnodeAsynchronously:replaceMe withNode:first completion:^(BOOL cancelled, ASDisplayNode *firstBlockArgument, ASDisplayNode *replaceMeBlockArgument) {
|
|
||||||
XCTAssertNil(firstBlockArgument, @"Should have cancelled");
|
|
||||||
XCTAssertNil(replaceMeBlockArgument, @"Should have cancelled");
|
|
||||||
firstFinished = YES;
|
|
||||||
}];
|
|
||||||
|
|
||||||
__block BOOL secondFinished = NO;
|
|
||||||
[parent replaceSubnodeAsynchronously:replaceMe withNode:second completion:^(BOOL cancelled, ASDisplayNode *secondBlockArgument, ASDisplayNode *replaceMeBlockArgument) {
|
|
||||||
XCTAssertNotNil(secondBlockArgument, @"Should have the relevant node passed in");
|
|
||||||
XCTAssertNotNil(replaceMeBlockArgument, @"Should have the relevant node passed in");
|
|
||||||
secondFinished = YES;
|
|
||||||
}];
|
|
||||||
|
|
||||||
XCTAssertTrue(replaceMe.supernode == parent, @"didn't remove old node");
|
|
||||||
XCTAssertTrue(first.supernode == nil, @"oops, added node too soon");
|
|
||||||
XCTAssertTrue(second.supernode == nil, @"oops, added node too soon");
|
|
||||||
XCTAssertFalse(first.nodeLoaded, @"first view loaded too soon");
|
|
||||||
XCTAssertFalse(second.nodeLoaded, @"second view loaded too soon");
|
|
||||||
|
|
||||||
// Allow first to complete, but verify that the nodes are nil, indicating cancellation (asserts are in blocks above)
|
|
||||||
dispatch_semaphore_signal(allowFirst);
|
|
||||||
|
|
||||||
// Let the work execute on the bg thread
|
|
||||||
ASDisplayNodeRunRunLoopUntilBlockIsTrue(^BOOL{ return firstFinished; });
|
|
||||||
|
|
||||||
XCTAssertTrue(first.supernode == nil, @"first should not be added to the hierarchy ever");
|
|
||||||
XCTAssertTrue(second.supernode == nil, @"second should not yet be added to the hierarchy");
|
|
||||||
|
|
||||||
dispatch_semaphore_signal(allowSecond);
|
|
||||||
ASDisplayNodeRunRunLoopUntilBlockIsTrue(^BOOL{ return secondFinished; });
|
|
||||||
|
|
||||||
XCTAssertTrue(first.supernode == nil, @"first should not be added to the hierarchy ever");
|
|
||||||
XCTAssertTrue(second.supernode == parent, @"second should be added now, woot!");
|
|
||||||
XCTAssertTrue(CGSizeEqualToSize(CGSizeMake(10, 20), [second calculatedSize]), @"Should have correct calculatedSize");
|
|
||||||
|
|
||||||
[parent release];
|
|
||||||
[first release];
|
|
||||||
[second release];
|
|
||||||
dispatch_release(allowFirst);
|
|
||||||
dispatch_release(allowSecond);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)testInsertSubnodeAtIndexView
|
- (void)testInsertSubnodeAtIndexView
|
||||||
{
|
{
|
||||||
[self checkInsertSubnodeAtIndexWithViewLoaded:YES layerBacked:NO];
|
[self checkInsertSubnodeAtIndexWithViewLoaded:YES layerBacked:NO];
|
||||||
|
|||||||
Reference in New Issue
Block a user