From efab1a4855f56a97eed09e483e5081b7e13d82a8 Mon Sep 17 00:00:00 2001 From: Michael Schneider Date: Thu, 16 Jun 2016 18:12:57 -0700 Subject: [PATCH 1/3] Move modifier to __weak for the highlighted layer in ASTextNode (#1756) --- AsyncDisplayKit/ASTextNode.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AsyncDisplayKit/ASTextNode.mm b/AsyncDisplayKit/ASTextNode.mm index 2a79fa80fa..5fc9ac2919 100644 --- a/AsyncDisplayKit/ASTextNode.mm +++ b/AsyncDisplayKit/ASTextNode.mm @@ -619,7 +619,7 @@ static NSArray *DefaultLinkAttributeNames = @[ NSLinkAttributeName ]; if (_activeHighlightLayer) { if (animated) { - __unsafe_unretained CALayer *weakHighlightLayer = _activeHighlightLayer; + __weak CALayer *weakHighlightLayer = _activeHighlightLayer; _activeHighlightLayer = nil; weakHighlightLayer.opacity = 0.0; From aa5d730eab80b0d105564fd96d7b2257b44007a8 Mon Sep 17 00:00:00 2001 From: Michael Schneider Date: Thu, 16 Jun 2016 18:18:43 -0700 Subject: [PATCH 2/3] Deallocate objects on a serial queue specific for deallocation (#1737) [Performance] Prevent GCD thread explosion due to object deallocation workloads (serial deallocation queue). --- AsyncDisplayKit/ASMultiplexImageNode.mm | 2 +- AsyncDisplayKit/ASNetworkImageNode.mm | 2 +- AsyncDisplayKit/ASTextNode.mm | 2 +- AsyncDisplayKit/Private/ASInternalHelpers.h | 9 ++++++++- AsyncDisplayKit/Private/ASInternalHelpers.mm | 11 +++++++++++ 5 files changed, 22 insertions(+), 4 deletions(-) diff --git a/AsyncDisplayKit/ASMultiplexImageNode.mm b/AsyncDisplayKit/ASMultiplexImageNode.mm index a1c6660fd6..19145359ba 100644 --- a/AsyncDisplayKit/ASMultiplexImageNode.mm +++ b/AsyncDisplayKit/ASMultiplexImageNode.mm @@ -531,7 +531,7 @@ typedef void(^ASMultiplexImageLoadCompletionBlock)(UIImage *image, id imageIdent BOOL shouldReleaseImageOnBackgroundThread = imageSize.width > kMinReleaseImageOnBackgroundSize.width || imageSize.height > kMinReleaseImageOnBackgroundSize.height; if (shouldReleaseImageOnBackgroundThread) { - ASPerformBlockOnBackgroundThread(^{ + ASPerformBlockOnDeallocationQueue(^{ image = nil; }); } diff --git a/AsyncDisplayKit/ASNetworkImageNode.mm b/AsyncDisplayKit/ASNetworkImageNode.mm index 3ce5e4b12f..279f1bca79 100755 --- a/AsyncDisplayKit/ASNetworkImageNode.mm +++ b/AsyncDisplayKit/ASNetworkImageNode.mm @@ -378,7 +378,7 @@ static const CGSize kMinReleaseImageOnBackgroundSize = {20.0, 20.0}; BOOL shouldReleaseImageOnBackgroundThread = imageSize.width > kMinReleaseImageOnBackgroundSize.width || imageSize.height > kMinReleaseImageOnBackgroundSize.height; if (shouldReleaseImageOnBackgroundThread) { - ASPerformBlockOnBackgroundThread(^{ + ASPerformBlockOnDeallocationQueue(^{ image = nil; }); } diff --git a/AsyncDisplayKit/ASTextNode.mm b/AsyncDisplayKit/ASTextNode.mm index 5fc9ac2919..fedcfaa091 100644 --- a/AsyncDisplayKit/ASTextNode.mm +++ b/AsyncDisplayKit/ASTextNode.mm @@ -260,7 +260,7 @@ static NSArray *DefaultLinkAttributeNames = @[ NSLinkAttributeName ]; // actually dealloc. __block ASTextKitRenderer *renderer = _renderer; - ASPerformBlockOnBackgroundThread(^{ + ASPerformBlockOnDeallocationQueue(^{ renderer = nil; }); _renderer = nil; diff --git a/AsyncDisplayKit/Private/ASInternalHelpers.h b/AsyncDisplayKit/Private/ASInternalHelpers.h index 8f154949a6..cff8c1fc53 100644 --- a/AsyncDisplayKit/Private/ASInternalHelpers.h +++ b/AsyncDisplayKit/Private/ASInternalHelpers.h @@ -17,8 +17,15 @@ ASDISPLAYNODE_EXTERN_C_BEGIN BOOL ASSubclassOverridesSelector(Class superclass, Class subclass, SEL selector); BOOL ASSubclassOverridesClassSelector(Class superclass, Class subclass, SEL selector); + +/// Dispatches the given block to the main queue if not already running on the main thread void ASPerformBlockOnMainThread(void (^block)()); -void ASPerformBlockOnBackgroundThread(void (^block)()); // DISPATCH_QUEUE_PRIORITY_DEFAULT + +/// Dispatches the given block to a background queue with priority of DISPATCH_QUEUE_PRIORITY_DEFAULT if not already run on a background queue +void ASPerformBlockOnBackgroundThread(void (^block)()); // DISPATCH_QUEUE_PRIORITY_DEFAULT + +/// Dispatches a block on to a serial queue that's main purpose is for deallocation of objects on a background thread +void ASPerformBlockOnDeallocationQueue(void (^block)()); CGFloat ASScreenScale(); diff --git a/AsyncDisplayKit/Private/ASInternalHelpers.mm b/AsyncDisplayKit/Private/ASInternalHelpers.mm index e18b932ce9..4d4ccbbf74 100644 --- a/AsyncDisplayKit/Private/ASInternalHelpers.mm +++ b/AsyncDisplayKit/Private/ASInternalHelpers.mm @@ -52,6 +52,17 @@ void ASPerformBlockOnBackgroundThread(void (^block)()) } } +void ASPerformBlockOnDeallocationQueue(void (^block)()) +{ + static dispatch_queue_t queue; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + queue = dispatch_queue_create("org.AsyncDisplayKit.deallocationQueue", DISPATCH_QUEUE_SERIAL); + }); + + dispatch_async(queue, block); +} + CGFloat ASScreenScale() { static CGFloat __scale = 0.0; From e55037354c0b65a02adb5981052bb59937e19775 Mon Sep 17 00:00:00 2001 From: Vadim Spivak Date: Thu, 16 Jun 2016 21:59:29 -0700 Subject: [PATCH 3/3] Round up editable text node to the next point (#1761) Rounding up to the next device pixel was calculating a height smaller than UITextView's contentSize. This was causing the baseline to move as the user was typing. --- AsyncDisplayKit/ASEditableTextNode.mm | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/AsyncDisplayKit/ASEditableTextNode.mm b/AsyncDisplayKit/ASEditableTextNode.mm index eb00be7941..48035a8da3 100644 --- a/AsyncDisplayKit/ASEditableTextNode.mm +++ b/AsyncDisplayKit/ASEditableTextNode.mm @@ -192,8 +192,7 @@ { ASTextKitComponents *displayedComponents = [self isDisplayingPlaceholder] ? _placeholderTextKitComponents : _textKitComponents; CGSize textSize = [displayedComponents sizeForConstrainedWidth:constrainedSize.width]; - textSize = ceilSizeValue(textSize); - return CGSizeMake(fminf(textSize.width, constrainedSize.width), fminf(textSize.height, constrainedSize.height)); + return CGSizeMake(fminf(ceilf(textSize.width), constrainedSize.width), fminf(ceilf(textSize.height), constrainedSize.height)); } - (void)layout