From 093653b507b46ba7c731fc350899cf8f4d53ad5d Mon Sep 17 00:00:00 2001 From: Garrett Moon Date: Tue, 18 Oct 2016 08:35:25 -0700 Subject: [PATCH 01/59] Upgrades to the latest PINRemoteImage (#2414) --- AsyncDisplayKit.podspec | 3 ++- .../Details/ASPINRemoteImageDownloader.m | 22 ++++++++++++++----- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/AsyncDisplayKit.podspec b/AsyncDisplayKit.podspec index bdcdb556ce..9e146ed38d 100644 --- a/AsyncDisplayKit.podspec +++ b/AsyncDisplayKit.podspec @@ -59,7 +59,8 @@ Pod::Spec.new do |spec| spec.subspec 'PINRemoteImage' do |pin| pin.xcconfig = { 'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) PIN_REMOTE_IMAGE=1' } - pin.dependency 'PINRemoteImage/iOS', '>= 3.0.0-beta.3' + pin.dependency 'PINRemoteImage/iOS', '>= 3.0.0-beta.4' + pin.dependency 'PINRemoteImage/PINCache' pin.dependency 'AsyncDisplayKit/Core' end diff --git a/AsyncDisplayKit/Details/ASPINRemoteImageDownloader.m b/AsyncDisplayKit/Details/ASPINRemoteImageDownloader.m index 241fb71810..6ae4a0437d 100644 --- a/AsyncDisplayKit/Details/ASPINRemoteImageDownloader.m +++ b/AsyncDisplayKit/Details/ASPINRemoteImageDownloader.m @@ -27,7 +27,7 @@ #import #import -#import +#import #if PIN_ANIMATED_AVAILABLE @@ -75,7 +75,7 @@ @implementation ASPINRemoteImageManager //Share image cache with sharedImageManager image cache. -- (PINCache *)defaultImageCache +- (id )defaultImageCache { return [[PINRemoteImageManager sharedImageManager] cache]; } @@ -124,6 +124,16 @@ return sharedPINRemoteImageManager; } +- (BOOL)sharedImageManagerSupportsMemoryRemoval +{ + static BOOL sharedImageManagerSupportsMemoryRemoval = NO; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedImageManagerSupportsMemoryRemoval = [[[self sharedPINRemoteImageManager] cache] respondsToSelector:@selector(removeObjectForKeyFromMemory:)]; + }); + return sharedImageManagerSupportsMemoryRemoval; +} + #pragma mark ASImageProtocols #if PIN_ANIMATED_AVAILABLE @@ -163,9 +173,11 @@ - (void)clearFetchedImageFromCacheWithURL:(NSURL *)URL { - PINRemoteImageManager *manager = [self sharedPINRemoteImageManager]; - NSString *key = [manager cacheKeyForURL:URL processorKey:nil]; - [[[manager cache] memoryCache] removeObjectForKey:key]; + if ([self sharedImageManagerSupportsMemoryRemoval]) { + PINRemoteImageManager *manager = [self sharedPINRemoteImageManager]; + NSString *key = [manager cacheKeyForURL:URL processorKey:nil]; + [[manager cache] removeObjectForKeyFromMemory:key]; + } } - (nullable id)downloadImageWithURL:(NSURL *)URL From d407663e3f59a5ce352727f7d361b09db9fb7087 Mon Sep 17 00:00:00 2001 From: Michael Schneider Date: Tue, 18 Oct 2016 08:36:38 -0700 Subject: [PATCH 02/59] [ASLayout] Improve ASLayout (#2404) * Add internal header for ASLayout and change position to readonly publicly * Don't copy sublayouts during tree filtering * Revert "Don't copy sublayouts during tree filtering" This reverts commit 6b0d54d5ffe5bb3941ec13696c9c45b0098b6ba1. --- AsyncDisplayKit.xcodeproj/project.pbxproj | 6 ++++- AsyncDisplayKit/ASDisplayNode.mm | 2 +- .../Layout/ASAbsoluteLayoutSpec.mm | 2 +- .../Layout/ASBackgroundLayoutSpec.mm | 2 +- AsyncDisplayKit/Layout/ASInsetLayoutSpec.mm | 2 +- AsyncDisplayKit/Layout/ASLayout.h | 2 +- AsyncDisplayKit/Layout/ASLayout.mm | 2 +- AsyncDisplayKit/Layout/ASLayoutPrivate.h | 25 +++++++++++++++++++ AsyncDisplayKit/Layout/ASLayoutSpec.mm | 2 +- AsyncDisplayKit/Layout/ASOverlayLayoutSpec.mm | 2 +- AsyncDisplayKit/Layout/ASRatioLayoutSpec.mm | 2 +- .../Layout/ASRelativeLayoutSpec.mm | 2 +- .../ASStackBaselinePositionedLayout.mm | 1 + .../Private/ASStackPositionedLayout.mm | 1 + 14 files changed, 42 insertions(+), 11 deletions(-) create mode 100644 AsyncDisplayKit/Layout/ASLayoutPrivate.h diff --git a/AsyncDisplayKit.xcodeproj/project.pbxproj b/AsyncDisplayKit.xcodeproj/project.pbxproj index 24f25a664f..390bc3e638 100644 --- a/AsyncDisplayKit.xcodeproj/project.pbxproj +++ b/AsyncDisplayKit.xcodeproj/project.pbxproj @@ -196,6 +196,7 @@ 68FC85EA1CE29C7D00EDD713 /* ASVisibilityProtocols.h in Headers */ = {isa = PBXBuildFile; fileRef = 68FC85E71CE29C7D00EDD713 /* ASVisibilityProtocols.h */; settings = {ATTRIBUTES = (Public, ); }; }; 68FC85EB1CE29C7D00EDD713 /* ASVisibilityProtocols.m in Sources */ = {isa = PBXBuildFile; fileRef = 68FC85E81CE29C7D00EDD713 /* ASVisibilityProtocols.m */; }; 68FC85EC1CE29C7D00EDD713 /* ASVisibilityProtocols.m in Sources */ = {isa = PBXBuildFile; fileRef = 68FC85E81CE29C7D00EDD713 /* ASVisibilityProtocols.m */; }; + 690457F71DB5131A00B5EE68 /* ASLayoutPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 690457F61DB5131A00B5EE68 /* ASLayoutPrivate.h */; }; 6959433E1D70815300B0EE1F /* ASDisplayNodeLayout.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6959433C1D70815300B0EE1F /* ASDisplayNodeLayout.mm */; }; 6959433F1D70815300B0EE1F /* ASDisplayNodeLayout.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6959433C1D70815300B0EE1F /* ASDisplayNodeLayout.mm */; }; 695943401D70815300B0EE1F /* ASDisplayNodeLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 6959433D1D70815300B0EE1F /* ASDisplayNodeLayout.h */; }; @@ -978,6 +979,7 @@ 68FC85E11CE29B7E00EDD713 /* ASTabBarController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASTabBarController.m; sourceTree = ""; }; 68FC85E71CE29C7D00EDD713 /* ASVisibilityProtocols.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASVisibilityProtocols.h; sourceTree = ""; }; 68FC85E81CE29C7D00EDD713 /* ASVisibilityProtocols.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASVisibilityProtocols.m; sourceTree = ""; }; + 690457F61DB5131A00B5EE68 /* ASLayoutPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASLayoutPrivate.h; path = AsyncDisplayKit/Layout/ASLayoutPrivate.h; sourceTree = ""; }; 6959433C1D70815300B0EE1F /* ASDisplayNodeLayout.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASDisplayNodeLayout.mm; sourceTree = ""; }; 6959433D1D70815300B0EE1F /* ASDisplayNodeLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASDisplayNodeLayout.h; sourceTree = ""; }; 696FCB301D6E46050093471E /* ASBackgroundLayoutSpecSnapshotTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASBackgroundLayoutSpecSnapshotTests.mm; sourceTree = ""; }; @@ -1108,8 +1110,8 @@ BDC2D162BD55A807C1475DA5 /* Pods-AsyncDisplayKitTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AsyncDisplayKitTests.profile.xcconfig"; path = "Pods/Target Support Files/Pods-AsyncDisplayKitTests/Pods-AsyncDisplayKitTests.profile.xcconfig"; sourceTree = ""; }; CC051F1E1D7A286A006434CB /* ASCALayerTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASCALayerTests.m; sourceTree = ""; }; CC0AEEA31D66316E005D1C78 /* ASUICollectionViewTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASUICollectionViewTests.m; sourceTree = ""; }; - CC2E317F1DAC353700EEE891 /* ASCollectionView+Undeprecated.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ASCollectionView+Undeprecated.h"; sourceTree = ""; }; CC11F9791DB181180024D77B /* ASNetworkImageNodeTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASNetworkImageNodeTests.m; sourceTree = ""; }; + CC2E317F1DAC353700EEE891 /* ASCollectionView+Undeprecated.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ASCollectionView+Undeprecated.h"; sourceTree = ""; }; CC3B20811C3F76D600798563 /* ASPendingStateController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASPendingStateController.h; sourceTree = ""; }; CC3B20821C3F76D600798563 /* ASPendingStateController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASPendingStateController.mm; sourceTree = ""; }; CC3B20871C3F7A5400798563 /* ASWeakSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASWeakSet.h; sourceTree = ""; }; @@ -1710,6 +1712,7 @@ 9C49C36E1B853957000B0DD5 /* ASStackLayoutElement.h */, ACF6ED161B17843500DA7C62 /* ASStackLayoutSpec.h */, ACF6ED171B17843500DA7C62 /* ASStackLayoutSpec.mm */, + 690457F61DB5131A00B5EE68 /* ASLayoutPrivate.h */, ); name = Layout; path = ..; @@ -1759,6 +1762,7 @@ 9C70F20D1CDBE9CB007D6C76 /* ASDefaultPlayButton.h in Headers */, 68355B411CB57A6C001D4E68 /* ASImageContainerProtocolCategories.h in Headers */, 7630FFA81C9E267E007A7C0E /* ASVideoNode.h in Headers */, + 690457F71DB5131A00B5EE68 /* ASLayoutPrivate.h in Headers */, B350623F1B010EFD0018CF92 /* _ASAsyncTransactionContainer.h in Headers */, B13CA1011C52004900E031AB /* ASCollectionNode+Beta.h in Headers */, 254C6B7E1BF94DF4003EC431 /* ASTextKitTailTruncater.h in Headers */, diff --git a/AsyncDisplayKit/ASDisplayNode.mm b/AsyncDisplayKit/ASDisplayNode.mm index d73593ccd5..38be76c287 100644 --- a/AsyncDisplayKit/ASDisplayNode.mm +++ b/AsyncDisplayKit/ASDisplayNode.mm @@ -30,7 +30,7 @@ #import "ASLayoutElementStylePrivate.h" #import "ASInternalHelpers.h" -#import "ASLayout.h" +#import "ASLayoutPrivate.h" #import "ASLayoutSpec.h" #import "ASCellNode+Internal.h" #import "ASWeakProxy.h" diff --git a/AsyncDisplayKit/Layout/ASAbsoluteLayoutSpec.mm b/AsyncDisplayKit/Layout/ASAbsoluteLayoutSpec.mm index 64ff4e2d31..1fdb527d31 100644 --- a/AsyncDisplayKit/Layout/ASAbsoluteLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASAbsoluteLayoutSpec.mm @@ -11,7 +11,7 @@ #import "ASAbsoluteLayoutSpec.h" #import "ASLayoutSpecUtilities.h" -#import "ASLayout.h" +#import "ASLayoutPrivate.h" #import "ASLayoutElementStylePrivate.h" @implementation ASAbsoluteLayoutSpec diff --git a/AsyncDisplayKit/Layout/ASBackgroundLayoutSpec.mm b/AsyncDisplayKit/Layout/ASBackgroundLayoutSpec.mm index 9271d70d70..3020f4cc86 100644 --- a/AsyncDisplayKit/Layout/ASBackgroundLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASBackgroundLayoutSpec.mm @@ -12,7 +12,7 @@ #import "ASLayoutSpec+Subclasses.h" #import "ASAssert.h" -#import "ASLayout.h" +#import "ASLayoutPrivate.h" static NSUInteger const kForegroundChildIndex = 0; static NSUInteger const kBackgroundChildIndex = 1; diff --git a/AsyncDisplayKit/Layout/ASInsetLayoutSpec.mm b/AsyncDisplayKit/Layout/ASInsetLayoutSpec.mm index 986d2e4002..ca20eadc51 100644 --- a/AsyncDisplayKit/Layout/ASInsetLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASInsetLayoutSpec.mm @@ -13,7 +13,7 @@ #import "ASAssert.h" #import "ASInternalHelpers.h" -#import "ASLayout.h" +#import "ASLayoutPrivate.h" @interface ASInsetLayoutSpec () { diff --git a/AsyncDisplayKit/Layout/ASLayout.h b/AsyncDisplayKit/Layout/ASLayout.h index 1c3c1af1e3..0e145c1399 100644 --- a/AsyncDisplayKit/Layout/ASLayout.h +++ b/AsyncDisplayKit/Layout/ASLayout.h @@ -65,7 +65,7 @@ ASDISPLAYNODE_EXTERN_C_END * * @discussion When being used as a sublayout, this property must not equal CGPointNull. */ -@property (nonatomic, assign, readwrite) CGPoint position; +@property (nonatomic, assign, readonly) CGPoint position; /** * Array of ASLayouts. Each must have a valid non-null position. diff --git a/AsyncDisplayKit/Layout/ASLayout.mm b/AsyncDisplayKit/Layout/ASLayout.mm index 40633813e0..3a7c8d52fa 100644 --- a/AsyncDisplayKit/Layout/ASLayout.mm +++ b/AsyncDisplayKit/Layout/ASLayout.mm @@ -8,7 +8,7 @@ // of patent rights can be found in the PATENTS file in the same directory. // -#import "ASLayout.h" +#import "ASLayoutPrivate.h" #import "ASDimension.h" #import "ASInternalHelpers.h" diff --git a/AsyncDisplayKit/Layout/ASLayoutPrivate.h b/AsyncDisplayKit/Layout/ASLayoutPrivate.h new file mode 100644 index 0000000000..1a2ac3d388 --- /dev/null +++ b/AsyncDisplayKit/Layout/ASLayoutPrivate.h @@ -0,0 +1,25 @@ +// +// ASLayoutPrivate.h +// AsyncDisplayKit +// +// Created by Michael Schneider on 10/17/16. +// Copyright © 2016 Facebook. All rights reserved. +// + +#pragma once + +#import "ASLayout.h" + +/** + * Private header of ASLayout for internal usage in the framework + */ +@interface ASLayout () + +/** + * Position in parent. Default to CGPointNull. + * + * @discussion When being used as a sublayout, this property must not equal CGPointNull. + */ +@property (nonatomic, assign, readwrite) CGPoint position; + +@end diff --git a/AsyncDisplayKit/Layout/ASLayoutSpec.mm b/AsyncDisplayKit/Layout/ASLayoutSpec.mm index bf8b583b44..9d17c2e0d7 100644 --- a/AsyncDisplayKit/Layout/ASLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASLayoutSpec.mm @@ -11,7 +11,7 @@ #import "ASLayoutSpec.h" #import "ASLayoutSpecPrivate.h" #import "ASLayoutSpec+Subclasses.h" - +#import "ASLayoutPrivate.h" #import "ASLayoutElementStylePrivate.h" @implementation ASLayoutSpec diff --git a/AsyncDisplayKit/Layout/ASOverlayLayoutSpec.mm b/AsyncDisplayKit/Layout/ASOverlayLayoutSpec.mm index dbd329cceb..fb0b939fbf 100644 --- a/AsyncDisplayKit/Layout/ASOverlayLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASOverlayLayoutSpec.mm @@ -12,7 +12,7 @@ #import "ASLayoutSpec+Subclasses.h" #import "ASAssert.h" -#import "ASLayout.h" +#import "ASLayoutPrivate.h" static NSUInteger const kUnderlayChildIndex = 0; static NSUInteger const kOverlayChildIndex = 1; diff --git a/AsyncDisplayKit/Layout/ASRatioLayoutSpec.mm b/AsyncDisplayKit/Layout/ASRatioLayoutSpec.mm index c5cd3372dd..be54b226dd 100644 --- a/AsyncDisplayKit/Layout/ASRatioLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASRatioLayoutSpec.mm @@ -17,7 +17,7 @@ #import "ASAssert.h" #import "ASInternalHelpers.h" -#import "ASLayout.h" +#import "ASLayoutPrivate.h" @implementation ASRatioLayoutSpec { diff --git a/AsyncDisplayKit/Layout/ASRelativeLayoutSpec.mm b/AsyncDisplayKit/Layout/ASRelativeLayoutSpec.mm index 07e0324be0..87b51efab7 100644 --- a/AsyncDisplayKit/Layout/ASRelativeLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASRelativeLayoutSpec.mm @@ -13,7 +13,7 @@ #import "ASRelativeLayoutSpec.h" #import "ASInternalHelpers.h" -#import "ASLayout.h" +#import "ASLayoutPrivate.h" @implementation ASRelativeLayoutSpec diff --git a/AsyncDisplayKit/Private/ASStackBaselinePositionedLayout.mm b/AsyncDisplayKit/Private/ASStackBaselinePositionedLayout.mm index 5956568105..5c0a86cbe9 100644 --- a/AsyncDisplayKit/Private/ASStackBaselinePositionedLayout.mm +++ b/AsyncDisplayKit/Private/ASStackBaselinePositionedLayout.mm @@ -11,6 +11,7 @@ #import "ASStackBaselinePositionedLayout.h" #import "ASLayoutSpecUtilities.h" +#import "ASLayoutPrivate.h" static CGFloat baselineForItem(const ASStackLayoutSpecStyle &style, const ASLayout *layout) { diff --git a/AsyncDisplayKit/Private/ASStackPositionedLayout.mm b/AsyncDisplayKit/Private/ASStackPositionedLayout.mm index 4cb5ca52ee..16fdd9ea1a 100644 --- a/AsyncDisplayKit/Private/ASStackPositionedLayout.mm +++ b/AsyncDisplayKit/Private/ASStackPositionedLayout.mm @@ -14,6 +14,7 @@ #import "ASInternalHelpers.h" #import "ASLayoutSpecUtilities.h" +#import "ASLayoutPrivate.h" static CGFloat crossOffset(const ASStackLayoutSpecStyle &style, const ASStackUnpositionedItem &l, From dec9e4e836330a63fa0be2f3bb4045a7a07ad565 Mon Sep 17 00:00:00 2001 From: appleguy Date: Tue, 18 Oct 2016 09:07:29 -0700 Subject: [PATCH 03/59] [ASDeallocQueue] Fix teardown of thread (doesn't currently happen due to singleton). (#2410) Although this didn't occur _currently_, the code was incorrect and needs to be fixed. --- AsyncDisplayKit/ASRunLoopQueue.mm | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/AsyncDisplayKit/ASRunLoopQueue.mm b/AsyncDisplayKit/ASRunLoopQueue.mm index 6d2bd9d2f6..42e5ea96e7 100644 --- a/AsyncDisplayKit/ASRunLoopQueue.mm +++ b/AsyncDisplayKit/ASRunLoopQueue.mm @@ -79,7 +79,7 @@ static void runLoopSourceCallback(void *info) { [_condition lock]; [_condition signal]; - // At this moment, the thread is guaranteed to be finished starting. + // At this moment, -init is signalled that the thread is guaranteed to be finished starting. [_condition unlock]; // Keep processing events until the runloop is stopped. @@ -87,6 +87,12 @@ static void runLoopSourceCallback(void *info) { CFRunLoopTimerInvalidate(timer); CFRunLoopRemoveTimer(runloop, timer, kCFRunLoopCommonModes); + CFRelease(timer); + + [_condition lock]; + [_condition signal]; + // At this moment, -stop is signalled that the thread is guaranteed to be finished exiting. + [_condition unlock]; } } @@ -116,6 +122,7 @@ static void runLoopSourceCallback(void *info) { [_condition lock]; [self performSelector:@selector(_stop) onThread:_thread withObject:nil waitUntilDone:NO]; [_condition wait]; + // At this moment, the thread is guaranteed to be finished running. [_condition unlock]; _thread = nil; } From 9f1643ebfdce5122c312ddbc94a26b66f8a801ac Mon Sep 17 00:00:00 2001 From: Michael Schneider Date: Tue, 18 Oct 2016 09:18:40 -0700 Subject: [PATCH 04/59] Final size should always be in constrainedSize in ratio spec (#2403) --- AsyncDisplayKit/Layout/ASRatioLayoutSpec.mm | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/AsyncDisplayKit/Layout/ASRatioLayoutSpec.mm b/AsyncDisplayKit/Layout/ASRatioLayoutSpec.mm index be54b226dd..8feafac781 100644 --- a/AsyncDisplayKit/Layout/ASRatioLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASRatioLayoutSpec.mm @@ -19,11 +19,15 @@ #import "ASInternalHelpers.h" #import "ASLayoutPrivate.h" +#pragma mark - ASRatioLayoutSpec + @implementation ASRatioLayoutSpec { CGFloat _ratio; } +#pragma mark - Lifecycle + + (instancetype)ratioLayoutSpecWithRatio:(CGFloat)ratio child:(id)child { return [[self alloc] initWithRatio:ratio child:child]; @@ -34,19 +38,25 @@ if (!(self = [super init])) { return nil; } + ASDisplayNodeAssertNotNil(child, @"Child cannot be nil"); ASDisplayNodeAssert(ratio > 0, @"Ratio should be strictly positive, but received %f", ratio); _ratio = ratio; - [self setChild:child]; + self.child = child; + return self; } +#pragma mark - Setter / Getter + - (void)setRatio:(CGFloat)ratio { ASDisplayNodeAssert(self.isMutable, @"Cannot set properties when layout spec is not mutable"); _ratio = ratio; } +#pragma mark - ASLayoutElement + - (ASLayout *)calculateLayoutThatFits:(ASSizeRange)constrainedSize { std::vector sizeOptions; @@ -71,7 +81,7 @@ }); // If there is no max size in *either* dimension, we can't apply the ratio, so just pass our size range through. - const ASSizeRange childRange = (bestSize == sizeOptions.end()) ? constrainedSize : ASSizeRangeMake(*bestSize, *bestSize); + const ASSizeRange childRange = (bestSize == sizeOptions.end()) ? constrainedSize : ASSizeRangeIntersect(constrainedSize, ASSizeRangeMake(*bestSize, *bestSize)); const CGSize parentSize = (bestSize == sizeOptions.end()) ? ASLayoutElementParentSizeUndefined : *bestSize; ASLayout *sublayout = [self.child layoutThatFits:childRange parentSize:parentSize]; sublayout.position = CGPointZero; @@ -80,6 +90,8 @@ @end +#pragma mark - ASRatioLayoutSpec (Debugging) + @implementation ASRatioLayoutSpec (Debugging) #pragma mark - ASLayoutElementAsciiArtProtocol From 6e76daf279e04e41fd2ef1cdd9dfeff8e3f844ba Mon Sep 17 00:00:00 2001 From: Adlai Holler Date: Tue, 18 Oct 2016 09:33:37 -0700 Subject: [PATCH 05/59] [Layout] Check Layout Spec Tree for Duplicated Elements (#2408) * Check layout spec tree for duplicated elements * Enable layout spec tree dedupe only in debug --- AsyncDisplayKit/ASDisplayNode.mm | 14 +++++ AsyncDisplayKit/Layout/ASLayoutSpec.mm | 51 +++++++++++++++++-- AsyncDisplayKit/Private/ASLayoutSpecPrivate.h | 9 ++++ AsyncDisplayKitTests/ASDisplayNodeTests.m | 12 +++++ 4 files changed, 81 insertions(+), 5 deletions(-) diff --git a/AsyncDisplayKit/ASDisplayNode.mm b/AsyncDisplayKit/ASDisplayNode.mm index 38be76c287..95a4a55f86 100644 --- a/AsyncDisplayKit/ASDisplayNode.mm +++ b/AsyncDisplayKit/ASDisplayNode.mm @@ -34,6 +34,11 @@ #import "ASLayoutSpec.h" #import "ASCellNode+Internal.h" #import "ASWeakProxy.h" +#import "ASLayoutSpecPrivate.h" + +#if DEBUG + #define AS_DEDUPE_LAYOUT_SPEC_TREE 1 +#endif NSInteger const ASDefaultDrawingPriority = ASDefaultTransactionPriority; NSString * const ASRenderingEngineDidDisplayScheduledNodesNotification = @"ASRenderingEngineDidDisplayScheduledNodes"; @@ -2426,6 +2431,15 @@ void recursivelyTriggerDisplayForLayer(CALayer *layer, BOOL shouldBlock) [self layoutSpecThatFits:constrainedSize]; }); +#if AS_DEDUPE_LAYOUT_SPEC_TREE + NSSet *duplicateElements = [layoutSpec findDuplicatedElementsInSubtree]; + if (duplicateElements.count > 0) { + ASDisplayNodeFailAssert(@"Node %@ returned a layout spec that contains the same elements in multiple positions. Elements: %@", self, duplicateElements); + // Use an empty layout spec to avoid crash. + layoutSpec = [[ASLayoutSpec alloc] init]; + } +#endif + ASDisplayNodeAssert(layoutSpec.isMutable, @"Node %@ returned layout spec %@ that has already been used. Layout specs should always be regenerated.", self, layoutSpec); layoutSpec.parent = self; // This causes upward propogation of any non-default layoutElement values. diff --git a/AsyncDisplayKit/Layout/ASLayoutSpec.mm b/AsyncDisplayKit/Layout/ASLayoutSpec.mm index 9d17c2e0d7..2b5a31be38 100644 --- a/AsyncDisplayKit/Layout/ASLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASLayoutSpec.mm @@ -148,11 +148,7 @@ { ASDisplayNodeAssert(_childrenArray.count < 2, @"This layout spec does not support more than one child. Use the setChildren: or the setChild:AtIndex: API"); - if (_childrenArray.count) { - return _childrenArray[0]; - } - - return nil; + return _childrenArray.firstObject; } #pragma mark - Children @@ -235,6 +231,51 @@ ASEnvironmentLayoutExtensibilityForwarding +#pragma mark - Framework Private + +- (nullable NSSet> *)findDuplicatedElementsInSubtree +{ + NSMutableSet *result = nil; + NSUInteger count = 0; + [self _findDuplicatedElementsInSubtreeWithWorkingSet:[[NSMutableSet alloc] init] workingCount:&count result:&result]; + return result; +} + +/** + * This method is extremely performance-sensitive, so we do some strange things. + * + * @param workingSet A working set of elements for use in the recursion. + * @param workingCount The current count of the set for use in the recursion. + * @param result The set into which to put the result. This initially points to @c nil to save time if no duplicates exist. + */ +- (void)_findDuplicatedElementsInSubtreeWithWorkingSet:(NSMutableSet> *)workingSet workingCount:(NSUInteger *)workingCount result:(NSMutableSet> * _Nullable *)result +{ + Class layoutSpecClass = [ASLayoutSpec class]; + + for (id child in self) { + // Add the object into the set. + [workingSet addObject:child]; + + // Check that addObject: caused the count to increase. + // This is faster than using containsObject. + NSUInteger oldCount = *workingCount; + NSUInteger newCount = workingSet.count; + BOOL objectAlreadyExisted = (newCount != oldCount + 1); + if (objectAlreadyExisted) { + if (*result == nil) { + *result = [[NSMutableSet alloc] init]; + } + [*result addObject:child]; + } else { + *workingCount = newCount; + // If child is a layout spec we haven't visited, recurse its children. + if ([child isKindOfClass:layoutSpecClass]) { + [(ASLayoutSpec *)child _findDuplicatedElementsInSubtreeWithWorkingSet:workingSet workingCount:workingCount result:result]; + } + } + } +} + @end #pragma mark - ASWrapperLayoutSpec diff --git a/AsyncDisplayKit/Private/ASLayoutSpecPrivate.h b/AsyncDisplayKit/Private/ASLayoutSpecPrivate.h index 7cea216551..8a606483f1 100644 --- a/AsyncDisplayKit/Private/ASLayoutSpecPrivate.h +++ b/AsyncDisplayKit/Private/ASLayoutSpecPrivate.h @@ -15,11 +15,20 @@ #import "ASEnvironmentInternal.h" #import "ASThread.h" +NS_ASSUME_NONNULL_BEGIN + @interface ASLayoutSpec() { ASDN::RecursiveMutex __instanceLock__; ASEnvironmentState _environmentState; ASLayoutElementStyle *_style; NSMutableArray *_childrenArray; } + +/** + * Recursively search the subtree for elements that occur more than once. + */ +- (nullable NSSet> *)findDuplicatedElementsInSubtree; + @end +NS_ASSUME_NONNULL_END diff --git a/AsyncDisplayKitTests/ASDisplayNodeTests.m b/AsyncDisplayKitTests/ASDisplayNodeTests.m index 49452caaf8..d325450018 100644 --- a/AsyncDisplayKitTests/ASDisplayNodeTests.m +++ b/AsyncDisplayKitTests/ASDisplayNodeTests.m @@ -21,6 +21,8 @@ #import "UIView+ASConvenience.h" #import "ASCellNode.h" #import "ASImageNode.h" +#import "ASOverlayLayoutSpec.h" +#import "ASInsetLayoutSpec.h" // Conveniences for making nodes named a certain way #define DeclareNodeNamed(n) ASDisplayNode *n = [[ASDisplayNode alloc] init]; n.name = @#n @@ -2139,4 +2141,14 @@ static bool stringContainsPointer(NSString *description, id p) { } } +- (void)testThatHavingTheSameNodeTwiceInALayoutSpecCausesExceptionOnLayoutCalculation +{ + ASDisplayNode *node = [[ASDisplayNode alloc] init]; + ASDisplayNode *subnode = [[ASDisplayNode alloc] init]; + node.layoutSpecBlock = ^ASLayoutSpec *(ASDisplayNode *node, ASSizeRange constrainedSize) { + return [ASOverlayLayoutSpec overlayLayoutSpecWithChild:[ASInsetLayoutSpec insetLayoutSpecWithInsets:UIEdgeInsetsZero child:subnode] overlay:subnode]; + }; + XCTAssertThrowsSpecificNamed([node calculateLayoutThatFits:ASSizeRangeMake(CGSizeMake(100, 100))], NSException, NSInternalInconsistencyException); +} + @end From 17dcd5f7ec8570775583c4edaac9db84b228f9e1 Mon Sep 17 00:00:00 2001 From: Samuel Hsiung Date: Tue, 18 Oct 2016 10:54:46 -0700 Subject: [PATCH 06/59] [ASTableNode] Add missing ASTableNode delegate flag setup (#2415) * add missing ASTableNode delegate flag setup * fix typo --- AsyncDisplayKit/ASTableView.mm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/AsyncDisplayKit/ASTableView.mm b/AsyncDisplayKit/ASTableView.mm index 55848f3298..04f3a5e494 100644 --- a/AsyncDisplayKit/ASTableView.mm +++ b/AsyncDisplayKit/ASTableView.mm @@ -352,10 +352,12 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell"; _asyncDelegateFlags.scrollViewDidScroll = [_asyncDelegate respondsToSelector:@selector(scrollViewDidScroll:)]; _asyncDelegateFlags.tableViewWillDisplayNodeForRow = [_asyncDelegate respondsToSelector:@selector(tableView:willDisplayNode:forRowAtIndexPath:)]; + _asyncDelegateFlags.tableNodeWillDisplayNodeForRow = [_asyncDelegate respondsToSelector:@selector(tableNode:willDisplayRowWithNode:)]; if (_asyncDelegateFlags.tableViewWillDisplayNodeForRow == NO) { _asyncDelegateFlags.tableViewWillDisplayNodeForRowDeprecated = [_asyncDelegate respondsToSelector:@selector(tableView:willDisplayNodeForRowAtIndexPath:)]; } _asyncDelegateFlags.tableViewDidEndDisplayingNodeForRow = [_asyncDelegate respondsToSelector:@selector(tableView:didEndDisplayingNode:forRowAtIndexPath:)]; + _asyncDelegateFlags.tableNodeDidEndDisplayingNodeForRow = [_asyncDelegate respondsToSelector:@selector(tableNode:didEndDisplayingRowWithNode:)]; _asyncDelegateFlags.scrollViewWillEndDragging = [_asyncDelegate respondsToSelector:@selector(scrollViewWillEndDragging:withVelocity:targetContentOffset:)]; _asyncDelegateFlags.tableViewWillBeginBatchFetch = [_asyncDelegate respondsToSelector:@selector(tableView:willBeginBatchFetchWithContext:)]; _asyncDelegateFlags.tableNodeWillBeginBatchFetch = [_asyncDelegate respondsToSelector:@selector(tableNode:willBeginBatchFetchWithContext:)]; From 5a8d0037ec96dc3af3e313d9af28c34575685516 Mon Sep 17 00:00:00 2001 From: Adlai Holler Date: Tue, 18 Oct 2016 11:00:09 -0700 Subject: [PATCH 07/59] Add wait method to ASCollectionNode (#2416) --- AsyncDisplayKit/ASCollectionNode.h | 5 +++++ AsyncDisplayKit/ASCollectionNode.mm | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/AsyncDisplayKit/ASCollectionNode.h b/AsyncDisplayKit/ASCollectionNode.h index b54d7ee79a..932c6de132 100644 --- a/AsyncDisplayKit/ASCollectionNode.h +++ b/AsyncDisplayKit/ASCollectionNode.h @@ -159,6 +159,11 @@ NS_ASSUME_NONNULL_BEGIN */ - (void)performBatchUpdates:(nullable __attribute((noescape)) void (^)())updates completion:(nullable void (^)(BOOL finished))completion; +/** + * Blocks execution of the main thread until all section and item updates are committed to the view. This method must be called from the main thread. + */ +- (void)waitUntilAllUpdatesAreCommitted; + /** * Inserts one or more sections. * diff --git a/AsyncDisplayKit/ASCollectionNode.mm b/AsyncDisplayKit/ASCollectionNode.mm index 664ca7cc13..111691b824 100644 --- a/AsyncDisplayKit/ASCollectionNode.mm +++ b/AsyncDisplayKit/ASCollectionNode.mm @@ -323,6 +323,11 @@ [self.view performBatchUpdates:updates completion:completion]; } +- (void)waitUntilAllUpdatesAreCommitted +{ + [self.view waitUntilAllUpdatesAreCommitted]; +} + - (void)reloadDataWithCompletion:(void (^)())completion { [self.view reloadDataWithCompletion:completion]; From ba80b8369545b15f37800d90c1115cbb74e500d7 Mon Sep 17 00:00:00 2001 From: Michael Schneider Date: Tue, 18 Oct 2016 12:00:01 -0700 Subject: [PATCH 08/59] [ASRelativeLayoutSpec] Fix ASRelatativeLayoutSpec behavior for ASRelativeLayoutSpecPositionStart (#2393) * Fix ASRelatativeLayoutSpec behavior for ASRelativeLayoutSpecPositionStart * Add updated images for snapshot tests --- AsyncDisplayKit/Layout/ASCenterLayoutSpec.h | 2 -- AsyncDisplayKit/Layout/ASCenterLayoutSpec.mm | 10 +++--- AsyncDisplayKit/Layout/ASRatioLayoutSpec.mm | 8 ++--- AsyncDisplayKit/Layout/ASRelativeLayoutSpec.h | 32 ++++++++++-------- .../Layout/ASRelativeLayoutSpec.mm | 28 +++++---------- .../ASAbsoluteLayoutSpecSnapshotTests.m | 3 +- .../ASRelativeLayoutSpecSnapshotTests.mm | 27 ++++++++++----- ...ngeIsGivenToChildWhenNotPositioning@2x.png | Bin 0 -> 4955 bytes ...ngeIsGivenToChildWhenNotPositioning@3x.png | Bin 10308 -> 0 bytes .../testWithOptions@2x.png | Bin 0 -> 6102 bytes .../testWithOptions@3x.png | Bin 12389 -> 0 bytes .../testWithOptions_CenterX@2x.png | Bin 0 -> 6650 bytes .../testWithOptions_CenterX@3x.png | Bin 12505 -> 0 bytes .../testWithOptions_CenterXCenterY@2x.png | Bin 0 -> 6662 bytes .../testWithOptions_CenterXCenterY@3x.png | Bin 12274 -> 0 bytes .../testWithOptions_CenterXEndY@2x.png | Bin 0 -> 6474 bytes .../testWithOptions_CenterXEndY@3x.png | Bin 12004 -> 0 bytes .../testWithOptions_CenterY@2x.png | Bin 0 -> 6073 bytes .../testWithOptions_CenterY@3x.png | Bin 12114 -> 0 bytes .../testWithOptions_EndX@2x.png | Bin 0 -> 5656 bytes .../testWithOptions_EndX@3x.png | Bin 11609 -> 0 bytes .../testWithOptions_EndXCenterY@2x.png | Bin 0 -> 5811 bytes .../testWithOptions_EndXCenterY@3x.png | Bin 11738 -> 0 bytes .../testWithOptions_EndXEndY@2x.png | Bin 0 -> 5534 bytes .../testWithOptions_EndXEndY@3x.png | Bin 11338 -> 0 bytes .../testWithOptions_EndY@2x.png | Bin 0 -> 5905 bytes .../testWithOptions_EndY@3x.png | Bin 11827 -> 0 bytes .../testWithSizingOptions@2x.png | Bin 0 -> 6102 bytes .../testWithSizingOptions@3x.png | Bin 12389 -> 0 bytes ...thSizingOptions_SizingMinimumHeight@2x.png | Bin 0 -> 4792 bytes ...thSizingOptions_SizingMinimumHeight@3x.png | Bin 9534 -> 0 bytes ...ithSizingOptions_SizingMinimumWidth@2x.png | Bin 0 -> 2582 bytes ...ithSizingOptions_SizingMinimumWidth@3x.png | Bin 3946 -> 0 bytes ...zingMinimumWidthSizingMinimumHeight@2x.png | Bin 0 -> 1965 bytes ...zingMinimumWidthSizingMinimumHeight@3x.png | Bin 2696 -> 0 bytes 35 files changed, 55 insertions(+), 55 deletions(-) create mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testMinimumSizeRangeIsGivenToChildWhenNotPositioning@2x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testMinimumSizeRangeIsGivenToChildWhenNotPositioning@3x.png create mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testWithOptions@2x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testWithOptions@3x.png create mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testWithOptions_CenterX@2x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testWithOptions_CenterX@3x.png create mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testWithOptions_CenterXCenterY@2x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testWithOptions_CenterXCenterY@3x.png create mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testWithOptions_CenterXEndY@2x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testWithOptions_CenterXEndY@3x.png create mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testWithOptions_CenterY@2x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testWithOptions_CenterY@3x.png create mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testWithOptions_EndX@2x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testWithOptions_EndX@3x.png create mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testWithOptions_EndXCenterY@2x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testWithOptions_EndXCenterY@3x.png create mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testWithOptions_EndXEndY@2x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testWithOptions_EndXEndY@3x.png create mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testWithOptions_EndY@2x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testWithOptions_EndY@3x.png create mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testWithSizingOptions@2x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testWithSizingOptions@3x.png create mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testWithSizingOptions_SizingMinimumHeight@2x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testWithSizingOptions_SizingMinimumHeight@3x.png create mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testWithSizingOptions_SizingMinimumWidth@2x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testWithSizingOptions_SizingMinimumWidth@3x.png create mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testWithSizingOptions_SizingMinimumWidthSizingMinimumHeight@2x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testWithSizingOptions_SizingMinimumWidthSizingMinimumHeight@3x.png diff --git a/AsyncDisplayKit/Layout/ASCenterLayoutSpec.h b/AsyncDisplayKit/Layout/ASCenterLayoutSpec.h index 12629e9e1c..a1474c4840 100644 --- a/AsyncDisplayKit/Layout/ASCenterLayoutSpec.h +++ b/AsyncDisplayKit/Layout/ASCenterLayoutSpec.h @@ -49,9 +49,7 @@ NS_ASSUME_NONNULL_BEGIN * Initializer. * * @param centeringOptions How the child is centered. - * * @param sizingOptions How much space will be taken up. - * * @param child The child to center. */ + (instancetype)centerLayoutSpecWithCenteringOptions:(ASCenterLayoutSpecCenteringOptions)centeringOptions diff --git a/AsyncDisplayKit/Layout/ASCenterLayoutSpec.mm b/AsyncDisplayKit/Layout/ASCenterLayoutSpec.mm index a1610671d6..cbd06bb8f9 100644 --- a/AsyncDisplayKit/Layout/ASCenterLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASCenterLayoutSpec.mm @@ -58,21 +58,19 @@ - (ASRelativeLayoutSpecPosition)horizontalPositionFromCenteringOptions:(ASCenterLayoutSpecCenteringOptions)centeringOptions { - BOOL centerX = (centeringOptions & ASCenterLayoutSpecCenteringX) != 0; - if (centerX) { + if ((centeringOptions & ASCenterLayoutSpecCenteringX) != 0) { return ASRelativeLayoutSpecPositionCenter; } else { - return ASRelativeLayoutSpecPositionStart; + return ASRelativeLayoutSpecPositionNone; } } - (ASRelativeLayoutSpecPosition)verticalPositionFromCenteringOptions:(ASCenterLayoutSpecCenteringOptions)centeringOptions { - BOOL centerY = (centeringOptions & ASCenterLayoutSpecCenteringY) != 0; - if (centerY) { + if ((centeringOptions & ASCenterLayoutSpecCenteringY) != 0) { return ASRelativeLayoutSpecPositionCenter; } else { - return ASRelativeLayoutSpecPositionStart; + return ASRelativeLayoutSpecPositionNone; } } diff --git a/AsyncDisplayKit/Layout/ASRatioLayoutSpec.mm b/AsyncDisplayKit/Layout/ASRatioLayoutSpec.mm index 8feafac781..00c1d584f3 100644 --- a/AsyncDisplayKit/Layout/ASRatioLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASRatioLayoutSpec.mm @@ -60,15 +60,15 @@ - (ASLayout *)calculateLayoutThatFits:(ASSizeRange)constrainedSize { std::vector sizeOptions; - // TODO: layout: isValidForLayout() call should not be necessary if INFINITY is used - if (!isinf(constrainedSize.max.width) && ASPointsValidForLayout(constrainedSize.max.width)) { + + if (ASPointsValidForSize(constrainedSize.max.width)) { sizeOptions.push_back(ASSizeRangeClamp(constrainedSize, { constrainedSize.max.width, ASFloorPixelValue(_ratio * constrainedSize.max.width) })); } - // TODO: layout: isValidForLayout() call should not be necessary if INFINITY is used - if (!isinf(constrainedSize.max.height) && ASPointsValidForLayout(constrainedSize.max.width)) { + + if (ASPointsValidForSize(constrainedSize.max.width)) { sizeOptions.push_back(ASSizeRangeClamp(constrainedSize, { ASFloorPixelValue(constrainedSize.max.height / _ratio), constrainedSize.max.height diff --git a/AsyncDisplayKit/Layout/ASRelativeLayoutSpec.h b/AsyncDisplayKit/Layout/ASRelativeLayoutSpec.h index 17f3ccfffd..31e6350849 100644 --- a/AsyncDisplayKit/Layout/ASRelativeLayoutSpec.h +++ b/AsyncDisplayKit/Layout/ASRelativeLayoutSpec.h @@ -13,25 +13,27 @@ #import /** How the child is positioned within the spec. */ -typedef NS_OPTIONS(NSUInteger, ASRelativeLayoutSpecPosition) { - /** The child is positioned at point 0 relatively to the layout axis (ie left / top most) */ - ASRelativeLayoutSpecPositionStart = 0, - /** The child is centered along the specified axis */ - ASRelativeLayoutSpecPositionCenter = 1 << 0, - /** The child is positioned at the maximum point of the layout axis (ie right / bottom most) */ - ASRelativeLayoutSpecPositionEnd = 1 << 1, +typedef NS_ENUM(NSUInteger, ASRelativeLayoutSpecPosition) { + /** The child is positioned at point 0 */ + ASRelativeLayoutSpecPositionNone = 0, + /** The child is positioned at point 0 relatively to the layout axis (ie left / top most) */ + ASRelativeLayoutSpecPositionStart = 1, + /** The child is centered along the specified axis */ + ASRelativeLayoutSpecPositionCenter = 2, + /** The child is positioned at the maximum point of the layout axis (ie right / bottom most) */ + ASRelativeLayoutSpecPositionEnd = 3, }; /** How much space the spec will take up. */ typedef NS_OPTIONS(NSUInteger, ASRelativeLayoutSpecSizingOption) { - /** The spec will take up the maximum size possible */ - ASRelativeLayoutSpecSizingOptionDefault, - /** The spec will take up the minimum size possible along the X axis */ - ASRelativeLayoutSpecSizingOptionMinimumWidth = 1 << 0, - /** The spec will take up the minimum size possible along the Y axis */ - ASRelativeLayoutSpecSizingOptionMinimumHeight = 1 << 1, - /** Convenience option to take up the minimum size along both the X and Y axis */ - ASRelativeLayoutSpecSizingOptionMinimumSize = ASRelativeLayoutSpecSizingOptionMinimumWidth | ASRelativeLayoutSpecSizingOptionMinimumHeight, + /** The spec will take up the maximum size possible */ + ASRelativeLayoutSpecSizingOptionDefault, + /** The spec will take up the minimum size possible along the X axis */ + ASRelativeLayoutSpecSizingOptionMinimumWidth = 1 << 0, + /** The spec will take up the minimum size possible along the Y axis */ + ASRelativeLayoutSpecSizingOptionMinimumHeight = 1 << 1, + /** Convenience option to take up the minimum size along both the X and Y axis */ + ASRelativeLayoutSpecSizingOptionMinimumSize = ASRelativeLayoutSpecSizingOptionMinimumWidth | ASRelativeLayoutSpecSizingOptionMinimumHeight, }; NS_ASSUME_NONNULL_BEGIN diff --git a/AsyncDisplayKit/Layout/ASRelativeLayoutSpec.mm b/AsyncDisplayKit/Layout/ASRelativeLayoutSpec.mm index 87b51efab7..d8f9bd717a 100644 --- a/AsyncDisplayKit/Layout/ASRelativeLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASRelativeLayoutSpec.mm @@ -54,31 +54,21 @@ - (ASLayout *)calculateLayoutThatFits:(ASSizeRange)constrainedSize { - // If we have a finite size in any direction, pass this so that the child can - // resolve percentages against it. Otherwise pass ASLayoutElementParentDimensionUndefined - // as the size will depend on the content - // TODO: layout: isValidForLayout() call should not be necessary if INFINITY is used + // If we have a finite size in any direction, pass this so that the child can resolve percentages against it. + // Otherwise pass ASLayoutElementParentDimensionUndefined as the size will depend on the content CGSize size = { - isinf(constrainedSize.max.width) || !ASPointsValidForLayout(constrainedSize.max.width) ? ASLayoutElementParentDimensionUndefined : constrainedSize.max.width, - isinf(constrainedSize.max.height) || !ASPointsValidForLayout(constrainedSize.max.height) ? ASLayoutElementParentDimensionUndefined : constrainedSize.max.height + ASPointsValidForSize(constrainedSize.max.width) == NO ? ASLayoutElementParentDimensionUndefined : constrainedSize.max.width, + ASPointsValidForSize(constrainedSize.max.height) == NO ? ASLayoutElementParentDimensionUndefined : constrainedSize.max.height }; - BOOL reduceWidth = (_horizontalPosition & ASRelativeLayoutSpecPositionCenter) != 0 || - (_horizontalPosition & ASRelativeLayoutSpecPositionEnd) != 0; - - BOOL reduceHeight = (_verticalPosition & ASRelativeLayoutSpecPositionCenter) != 0 || - (_verticalPosition & ASRelativeLayoutSpecPositionEnd) != 0; - // Layout the child const CGSize minChildSize = { - reduceWidth ? 0 : constrainedSize.min.width, - reduceHeight ? 0 : constrainedSize.min.height, + (_horizontalPosition != ASRelativeLayoutSpecPositionNone) ? 0 : constrainedSize.min.width, + (_verticalPosition != ASRelativeLayoutSpecPositionNone) ? 0 : constrainedSize.min.height, }; - ASLayout *sublayout = [self.child layoutThatFits:ASSizeRangeMake(minChildSize, constrainedSize.max) parentSize:size]; - // If we have an undetermined height or width, use the child size to define the layout - // size + // If we have an undetermined height or width, use the child size to define the layout size size = ASSizeRangeClamp(constrainedSize, { isfinite(size.width) == NO ? sublayout.size.width : size.width, isfinite(size.height) == NO ? sublayout.size.height : size.height @@ -104,9 +94,9 @@ - (CGFloat)proportionOfAxisForAxisPosition:(ASRelativeLayoutSpecPosition)position { - if ((position & ASRelativeLayoutSpecPositionCenter) != 0) { + if (position == ASRelativeLayoutSpecPositionCenter) { return 0.5f; - } else if ((position & ASRelativeLayoutSpecPositionEnd) != 0) { + } else if (position == ASRelativeLayoutSpecPositionEnd) { return 1.0f; } else { return 0.0f; diff --git a/AsyncDisplayKitTests/ASAbsoluteLayoutSpecSnapshotTests.m b/AsyncDisplayKitTests/ASAbsoluteLayoutSpecSnapshotTests.m index 24231dde26..93c5c72e44 100644 --- a/AsyncDisplayKitTests/ASAbsoluteLayoutSpecSnapshotTests.m +++ b/AsyncDisplayKitTests/ASAbsoluteLayoutSpecSnapshotTests.m @@ -63,7 +63,8 @@ ASLayoutSpec *layoutSpec = [ASBackgroundLayoutSpec backgroundLayoutSpecWithChild: - [ASAbsoluteLayoutSpec absoluteLayoutSpecWithChildren:children] + [ASAbsoluteLayoutSpec + absoluteLayoutSpecWithChildren:children] background:backgroundNode]; [self testLayoutSpec:layoutSpec sizeRange:sizeRange subnodes:subnodes identifier:identifier]; diff --git a/AsyncDisplayKitTests/ASRelativeLayoutSpecSnapshotTests.mm b/AsyncDisplayKitTests/ASRelativeLayoutSpecSnapshotTests.mm index 3fa2df4d39..d507f4b77f 100644 --- a/AsyncDisplayKitTests/ASRelativeLayoutSpecSnapshotTests.mm +++ b/AsyncDisplayKitTests/ASRelativeLayoutSpecSnapshotTests.mm @@ -21,6 +21,16 @@ static const ASSizeRange kSize = {{100, 120}, {320, 160}}; @implementation ASRelativeLayoutSpecSnapshotTests +#pragma mark - XCTestCase + +- (void)setUp +{ + [super setUp]; + + self.recordMode = NO; +} + + - (void)testWithOptions { [self testAllVerticalPositionsForHorizontalPosition:ASRelativeLayoutSpecPositionStart]; @@ -29,7 +39,8 @@ static const ASSizeRange kSize = {{100, 120}, {320, 160}}; } -- (void)testAllVerticalPositionsForHorizontalPosition:(ASRelativeLayoutSpecPosition)horizontalPosition { +- (void)testAllVerticalPositionsForHorizontalPosition:(ASRelativeLayoutSpecPosition)horizontalPosition +{ [self testWithHorizontalPosition:horizontalPosition verticalPosition:ASRelativeLayoutSpecPositionStart sizingOptions:{}]; [self testWithHorizontalPosition:horizontalPosition verticalPosition:ASRelativeLayoutSpecPositionCenter sizingOptions:{}]; [self testWithHorizontalPosition:horizontalPosition verticalPosition:ASRelativeLayoutSpecPositionEnd sizingOptions:{}]; @@ -76,19 +87,19 @@ static const ASSizeRange kSize = {{100, 120}, {320, 160}}; static NSString *suffixForPositionOptions(ASRelativeLayoutSpecPosition horizontalPosition, ASRelativeLayoutSpecPosition verticalPosition, - ASRelativeLayoutSpecSizingOption sizingOptions) + ASRelativeLayoutSpecSizingOption sizingOptions) { NSMutableString *suffix = [NSMutableString string]; - if ((horizontalPosition & ASRelativeLayoutSpecPositionCenter) != 0) { + if (horizontalPosition == ASRelativeLayoutSpecPositionCenter) { [suffix appendString:@"CenterX"]; - } else if ((horizontalPosition & ASRelativeLayoutSpecPositionEnd) != 0) { + } else if (horizontalPosition == ASRelativeLayoutSpecPositionEnd) { [suffix appendString:@"EndX"]; } - if ((verticalPosition & ASRelativeLayoutSpecPositionCenter) != 0) { + if (verticalPosition == ASRelativeLayoutSpecPositionCenter) { [suffix appendString:@"CenterY"]; - } else if ((verticalPosition & ASRelativeLayoutSpecPositionEnd) != 0) { + } else if (verticalPosition == ASRelativeLayoutSpecPositionEnd) { [suffix appendString:@"EndY"]; } @@ -122,8 +133,8 @@ static NSString *suffixForPositionOptions(ASRelativeLayoutSpecPosition horizonta ASRelativeLayoutSpec *layoutSpec = [ASRelativeLayoutSpec - relativePositionLayoutSpecWithHorizontalPosition:ASRelativeLayoutSpecPositionStart - verticalPosition:ASRelativeLayoutSpecPositionStart + relativePositionLayoutSpecWithHorizontalPosition:ASRelativeLayoutSpecPositionNone + verticalPosition:ASRelativeLayoutSpecPositionNone sizingOption:{} child:childSpec]; diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testMinimumSizeRangeIsGivenToChildWhenNotPositioning@2x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testMinimumSizeRangeIsGivenToChildWhenNotPositioning@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..02717f8fdb7afa87892b61d4e4638fa5ea022138 GIT binary patch literal 4955 zcmeAS@N?(olHy`uVBq!ia0y~yU}|7sV07SM1B&RJJqwaxEDmyaVpw-h<|UBBS>O>_ z%)lU~3c`$@K`I}Bf-;#d{vkk`35Y>p0T63IX&{>`X7S`@Kt7j-r;B4q1>>6=2YHVe z@Gv`mzhA=i|1g_b@d42VjHz6f=Pmo~nI(UmJMdB2p@D&s$(8Zw|JXk^DbP0l+XkKb|Z(7 literal 0 HcmV?d00001 diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testMinimumSizeRangeIsGivenToChildWhenNotPositioning@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testMinimumSizeRangeIsGivenToChildWhenNotPositioning@3x.png deleted file mode 100644 index 3fb6feee42c18653fd93b4ccd872720f61f834a7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10308 zcmeAS@N?(olHy`uVBq!ia0y~yU_QXW!1#cJ4JeZJl%)koF%}28J29*~C-V}>;Vkfo zEM{O(v;bj7*J*|cKtY*I7yl3-%>=|C@BxT5pfr#znrb*Js0&CNdb&7HIBxM=z{@c$h>1DlwXg&hlrfPzB<10xel*MUQeugmJD zOIBHCa zrkU_&95|u|F&Zd3fkj7j8W(Ry!qP^QH!=wE4WB-g`g_k}Gf7AihB|~pz=LTTmv<|h z$%ab~Qe}Jy@rcSFyOyi^GD{h3M7U0c(Ytl26SGuArUI{ZJ3@SoP0iiQla?{^&bWc> z=B0;%7Bcd#F`3Xd_b@^{Om5%1OwY>=Y(6_xy%Va_0 zRJKbSif6#Z51cxD-BveK>Ow=OFFZIEI3u)lL`Q=eoE%4kc{DW(D2x^wqlLz3*^H>_ zMytTlmIg!PXiHAq(7ea`FC4#2_2j0Zp9O>_ z%)lU~3c`$@K`I}Bf-;#d{vkk`35Y>p0T63IX&{@YO8rPnFpzfhba4!+V0?39V=jv$ z5A%Vy`(J+E&1|&9pu*zzlO+>AEu3^A>inJGcEe%-yVpWYi0RQAdH=GEzKb@ea42JlNJ0Numlz_?*m!_ve| zu$2ZI@*Nn~JUV}Mcig{Ng3A2sGZgXsOa1!0@Vc{Y3Mixm7+4RiVw%>r^dQLF2M+9GWZckYAO61T zXSpOnWj~j`dFAcA-~LP0igs{tGA&?;2t9CVg9+GW5;x2h7{We2e-*3$Uyq>@sL7D*n1|di`{Q%0?60Xkx>cCPx$7Xvv1B030pZMypXgwe4s%I@)H# z*R&h4ZMH^xV8`PB|2W5kT?`D|jG!LH+nd&tWDI#+4(|QGG+bVqEpbtNo6|iDmPsL@ zub)4^E-zd$|G@k6=hyE~1GON5t>awg`u~>SkF(rUe{ksjz7OBh>%r~6|De|8hb$&J zK7MvcTlG7zQNH@e=YLDztlnSp@_l@j^%i);F~;}6;)fR@&CmzH_I812{k~tZ@BhZ= z{r&5m-(CjqfUM@MFtLHQFz*1H((4|b|2=)v`hS;}?yrCO_5vTQZ&6^%*x%+3?WurT z$)SIKzAE4Qy?E!B@A`XXZ^63_>(m}x{Ez|ZgcJZ9z&pC^-^ZWY_se_wzkf@&J6pqh z1Xo#Xq~xHr@H=1+Dg5K})%U;NJOA|3{rz9cGT_C}j#&-vhZjS;4!}Or1Fe61>NS7A z(vSW1d-^@TxA1B#T=+vq1+-VN1K9nEIXZuR-Sukw>E8AKFWp`!3u~f300ts&KeWL= z8i+$G5dS?BaW-HEcaMO?f)rr?t)brg!Q89N=OMZ0|NrGIj4TKR2gDuX8EP59sSem< zpTWpzuwqY(ibKpG8&(NGvI7e-4*wqaRE{9x8=lT9y(R=fmk6*G9c`njxgN@xNADqqmy literal 0 HcmV?d00001 diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testWithOptions@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testWithOptions@3x.png deleted file mode 100644 index c2bf62b0786395a78fa42272875d4077801e4be0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12389 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 L`8ijzmHPhxC;K!Q literal 0 HcmV?d00001 diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testWithOptions_CenterX@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testWithOptions_CenterX@3x.png deleted file mode 100644 index f1d9c2e52fe5a5f7ce81ea0b9bd77fae471de712..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12505 zcmeHOeM}Q)7{8D9pl}3I)Ry5!H&I;X=wUN3ld-FTQKGSokg3_E$JB<8z*s;6}4e}wyj=e4I-TedEANy;0o7_j= z=e@VjJ@>rN^LwA)_2cA&i2;7k`5_1rkfe)GK@i-EAn3R+0a~*DkeI*$%}+_(hcxwX zeF(nD@^nY?5#+@^t_@A7iDE$G*35W)DmY?bbA9Y!+vz!ibERX#bXg9LKPJU%Q;X2) zVePpdij-(qSMQzcQQN+Ln_6tg_Pm_;xDhY_Q3FWgS|jkm(q`xm97i^4K-jVj78@UGdE-Vq=Pat&LD>fsMT(?Mr|^9V);7*t`JfEgBI1_-wxfP~l^t|s96 z2rez*Vj0#MVC4iBonRRaRv=+b6_%s_7X|kEB_9M?U5&V!;)@^(lZ(-q8PVo$iweSN z7oTx2aNu;zw?We%`ebyNw=67|#~D_STM?Wr2zgrS1e8W5*8f9O{^0DxrQV1Nr5 zFsdw$l}bstNYuu8MD$6(YRpMS`=w7tPLh<>I^&^2M#+go6^3e7EQ(%ZNk++rNO?6~ zPmkSTUbyL=xAzgu7hFw$&OLiH>kot?5#bS`LkXC?H#lRj!gg#p3fyp8=o+^IZp`2; z12{k=@?hf(jk!ZdW5rm`WM%QRn_MZxeN_~=I)|8Rw5WklBntJ4QUULx(wk@AqpFVH z0jB-cOV;$!w@V6KPsHvfHFg^EQv zUQzNpQ zNEil%bOv*lD4oHaC14K-Fa+!Y0fqn+A;9==00uz7F2L>HIf?Sk?G-wW<7|lQg(>is zlV`Vy2}BG&+$ryOw`2>s)9TlP*~BA|2b9UI_7Z#BUU%ZH=2l^7@>an5z5m)i?Ue5b zTjmuZcY$FxGtyeI63SZ2jGT%?%YJ|D?x$%vA{C25*YACQ|H#Vr195ZdyzYm=Ft1qs zDAA3R6qQb+L>cDj&aMgR9Nq1;2zc!*di~xV7h9J0*OpH7@Fr+sX!ISRxyW`(hUsQ8 z(jl2YJ-kcv(f22KMVRrN^?Mhn(`PSI%e`lK6EIyYb`5AQGAdZonNX>6UN+_5e8f1P zb(dGfY8~64cUt!Yb^6@-K;8t_N>q9nXf84;pm1ckA2k&`ph)}9HZ@ekE5dSZ8}#lp zbsD-SwuSK~;G{TklWT}ZFe*3;CN?nx5oYx*<7b17ukwl@_y-&GE|Ha3Og|;Y2`2Cd z!vM{Vf>FWQ4&a$)J#8rJ+kNHGySySO@nD1AOY+5X*@dc7!Rw)eLkAc6m3KNo2N$NF zH{Qbt&gV)#-opqkWFtP_!w4?q7cZcJ5JiLxynyCkLzD`ezB}yd;LKUqUk{QJ4#qd_ HV=Dgv;q`6* diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testWithOptions_CenterXCenterY@2x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testWithOptions_CenterXCenterY@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..311ef9ed327356205ab0e43cfee0f69c3c85b6c4 GIT binary patch literal 6662 zcmeHMZA?>F7(TbRz0z`t4O*y(icUp0gcdRyqSBTzgiWnNb($Ku0|}T6=m><#w=Ol*T#Uwk6u3p(*lFdAQ47O1jo`jI#xyz+V0%j%9Qoj{+Zk+C#UE1 zIVbP?-1olcJx^)Kb=G$k{?QB3^;O0f<_H3yVhUgq(y$CmzB|O%^nKk<4-uTOeU5O( zc#nc5z9B&Ka3OV_DymGB4EK#k}PeEy?V1 zfU(rEVI%pUuS|%pfcEd=B1A?DW0l`IGC#`;%~9 zugBZ?cXPB_ab~@pxTbu%URqKUBbb?(d92Y9QUQ@V@i=Iy7C5j}G{7~$V1jlp!ls8>(s`Z0+nBzQ^2__1bP*hF$ zwY&KjJZZ36Iw#l~Go4l^(H=uM>3~m=hAv0xZXWJhie}dxY!FA0hG98k)0mVyB1HXa zMNXlUm(;3bYO9yvYNZArvHs8quqv}JCCR3oYHM9fd0*aNpbV{3eU+| zJ~ZM+=Sj<^(X9v6M3$jujn%mbA0+6TUL1*FiTA8~MG{*HUY7Lm(_9jI=;e|nCov_B zMk+4$hK~$(pM4b^g%wFp>EF`RM#So##;cODXyS<62QoJol|e#bRr-=SmS&b_Hk#R_ z!6pqhHz$hTq$4nb>yts7I((XplvY@w0#+?mfIP#%#9_^a&ip!NE)M0M0#9Br8tfdx zyp*)Ir1*qW1r%n}K~aTIxJB^$@Q{SM?4es5RL|l&7%|rv2w@GON;E59wc}qYHWzA0 zdu%N?hw7tsXY*)jjX_qxCMd(okI zV-iEz%|HlGF{m66_#fux*F{|+q^F(JIy%|1>8vG^aWFd&LN5d6qT_xQetDpW&xXev d7#@^7wrW{H&9};j@b4Lr@&5MID=Ea$e*m2=yp;d| literal 0 HcmV?d00001 diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testWithOptions_CenterXCenterY@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testWithOptions_CenterXCenterY@3x.png deleted file mode 100644 index 8093c8976182b151e956da8fe503b78d47c45047..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12274 zcmeAS@N?(olHy`uVBq!ia0y~yU_QXW!1#cJ4JeZJl%)koF%}28J29*~C-V}>;Vkfo zEM{O(v;bj7*J*|cKtY*I7yl3-%>=|C@BxT5pfr#zzH(ySzR5tk)YHW=q=NCyEyuhV zO97XI`~ELY-I;gcMDJe-i8Fa05|=qm)v2^315ReKgbVW<-W@&PEstzaM1$@Du>_bhum-r=t>?2x z)dIt8G#nslXEYo}!vR=QjFu0Of^{?;M#BMX9gC}+)Z3>CbuXAjhU{m#nivA|4xj{9{(V0+Hs?B34DA(YEncOo3eNaiB@Cz*tiYxe`_6?gjSqoeSWbNXv~39X$}QYQ^b@xOq|mr!5_&uUYK!ECnC9l4eEx5 ztFBB!H-wRlV}=>``|5phpeqn=*xm?r!>E@=V`((u!SnNIUIG_Uqs7B$AwF6!jaIdg z#>i;vVYH1m+H8e2>_=PTkiN=j=VG)Ai0Dz))cpgF!~g%!_F*w_L|^ zLmn5$`~NTX9cIord^cHf#?zXHw@p!3p8x(?^LH|+TYbUk!_Qxn8(6k+T8KwKUv&TS z`;)+aH(OnO(*#Jbd&AxzzyAwOXei!TrZ=lSlTG4>`G?=aEj*wu`z*%O-N0_W|AI2T z8IX?mWkmj5|8JiHBj=TKte;<40f*NTcJZe0 z`bKVi%Jui8&Ahl;7s;r6;EF=-4XiVeLtMfl@c>>EsHV9^GSyE(wPWBbceqM!JFy1~yA?Qr!En(!$9!o5B+?Mv2a zgi!}>HvrAfVFWF&K*XINFz%Y`n08Iy@ZEbx&6C4$^#upxgAZnS((gOfH-ClH w4a`6LoAFG0szFB%hR#}Kq&wajR1$1xXw=Y0aBEmkqYX&qW^$DLiEem z7Xc7Ho1I8z_IplfjLuJ6y%w%0ob0HBQyy61ci}6ds(BM!TQbv9)|McHy=OkdQV3qk zliI}D>7ZrF%8C!~+(Ji(iW%3q;flYLLU0Mmems+Sa*B2Linre-lr+EyrBkN?FZs74 z$iRlLq@h47y6a0!4j4iKUvsKF@c&P69^HHOy!vkgPlIF)XeW<1S0ae=g8tO%DFcFJ zf!m{#7n8Cr8t~2g8wPGo88jdaoLB$*+R<}U2JTue$Rx#4ihF?q^@A%HTycbb=5;y{ zitow$+%(5I6e5^*6~WwM0cE~n|JuN$*A&P3tLQE0cXMq==MhbXEXj-rA?e-V-?I&! z?{+J8CY@_-r-0<5Z!WLKo-9v`oYA|IuF^9r8?;H`us7xb3|~}XwSQ0PWzkB#ePVBO zn>(*B|N6|bkWc3*zZia4b(J2&VXy3tpeb`_|4`!`#|{&-qj70cHNk>0r8>Ohds9y= zFn98*L)@dsyvQ?nwDXfg;*9txjf2>+2{9D z3bYGCu{Cz4N2+_HThRF9v{|wFuFT@IvObr~>+>8p6HQ0Ww(=Ohzn(HWN7N35$&}z6 zpKih9ox5;*E%mUA@UsMgR?X##bJg z08Cj-#~t3b>#-P6X8G5F>V@IF6UXQusOIiok)dFW07zW~t-+5B@2o)SIx+4m^t=hM z{=&+rR)d$wmp91uo7=05GqFO}5siW}6LI}R^Z8-ED84O2oeRA%4_i^kPiJH@7RBI~ z*K!?24|G5Pnx~ut_;#hk)M^3}xvBM`j3{g04sr%A%liw+`~vjYgaT|2Ri>>gIilH>Xw43UKW)*}Mlx3m6 z%<^!W0t3+u)L!quO^l7~J#TQ{GNt}=f2z^cq2UOB)X<@Tze(Bq~#E%}m P0&rxeuS%;=B`tpe;{dF1 literal 0 HcmV?d00001 diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testWithOptions_CenterXEndY@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testWithOptions_CenterXEndY@3x.png deleted file mode 100644 index d9dab946b4e9a78e904c124a72b6123267bb9b48..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12004 zcmeHMUrbY196tBA?dj>o>1Q2&EJk6_z8U5)h)qWES74dBvQ=9aUd`U?1w6*s_R! zsO?2x)+3ZvKpM6GQXYqIZuz>OKXX@mP?Q! zYx@o|1Ty3uK_{3Nb_eVZBFn%Gzzo0)z>3s7C;}(~D1z)ajbDkqO~HK#FBWOhHo>e(H|N z9{Wq$ki*fQt6tAm-%bOY7SLuPpK#d8*%QD<8&US9kO!EmG+P8w&L)W1vb@87Jf$a?2AaG1&=y+ zTim_y84ee3pUQL)dFV;MumgjT)IIYXCSLR&$KeZ45uHpxckrQKoyUySdk|6*5S~0> zO2obVtwz_`kuxN`F~f{_8F^xA6c7gZI0W->yF>kKn-aMyf!xy-{ocitC?Vu0AQb8F zs)gP|j^fCL$kZPOJgO1`8;3wGR>^CrK%SC7KGYlxCE-yO5S}I=z~aH;!OoM(19qN* zJpOyybh|g=8f`3Q`sL+GgwpPl;_ULQrS+as!&qXmsn&aj@!m3{e~2#FZolqs>YVM; z5LLLuyWbX@X&ddYvKfMVBAuA=cdazFT%a)bmzw%3!x1Nw%^7C=*Uq+AJ9sDW)t-}| z?4a6o>LSkCJ)j%^NmiJpxKh-x{@`Z>H(%9BV#Go(Eh&R$#PG58|ex|0;wR@N- z)==#`{_U>joWaj6^rjojNxs*zxD3ZdqJy%+AEm+6$%h_D268xpWPoG%ke71%qab<_U4dU3Yw RIexK$iuWHZ?Ayn+{0(j_dR71c diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testWithOptions_CenterY@2x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testWithOptions_CenterY@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..94db1b131f8cf4a64ff4b9db4d50fca3af708f7b GIT binary patch literal 6073 zcmeHLdrVVT7(chribx|NBDFFf$yjt_ZB-a?PezPfe^xDM4>nn#8znybYP+F&bhaMcQmn?}TRtJkX~c9xJ?O_{_!F1ipCR^?I|Y%NBvzytz9(APTF#@2pmeU>$rybhUM915Co z1-1{zSR4snyefb(ka0__;>Dv&crO$%h3QMZ)~6PQf)?(urO>g8d?OBL)#M~CC6fC% zSlca2zgS&LybNOn3bFRC7Vp?OtU%MX61{V`l9)<}U>OL;bsN3oaMmmXr(+*=J+(Ks~~Ay@#!Q{xEs2|;9jLv`Eq zR2b!8Xlk6PB`c?=;$O0Vm;b@QE;f!o+0GmezZw(GCWGI}hS4nBi6xoiM-^2kiS%Gd z7O02$xwR^(G=obf%qYxNrm2ciVo(n`cFbRd@-xu1!hO@JlY7MHO0+){nI<%%)H(IG zWN6}K)_g}9%0(eK^+%ga`@D<)E?ab*Om$TNOasn`ruMP<%}XrHQHtY$^XtWQvt!tJ zuj6VAnbt#bC{I(FAxclXwPML?l=wk->SUwwY_n6V-6JK7OM3yzxyoRU(_PV%v|%q< zJ1WOVEc$+zd>8i|i>x6oR1^f4@e12g#fHu#!U34z%lI)(UAplns!JrZU6Q5j(R+BJ zTOCAkl9Zd#Mr{rkjJlF)Pbz*x4p;^@zkKRW`_rPKcS*HPF=o!C_3)$YyIHOdT9+Jl zh;43tG_8jxM7`D7AJe*|)?n>ZYiK=Os9t%*A)ck3zF?Sh-|;;U3X@8LQtTo(WA|a|7`KuU1b$zaSx6M zhS#(`wU!3of5+}RYH(l1NVw}`sXXtGZD9_E3+#OXwQ489hV6L}Eb+?VjL3y^reP5x z`Tgv>_3jP|AR~06GKJL1UZ*b3!=tbT0?8==wfSY9JFVWKp|Ax4dMStkc|o_l`IUST z1-B8+pr9v2=n+j_jWLD-w1^i_;0}_OdV{sqc#n1s-x<#yaA_$lfFLatEUp~C?hqHa z#q?{K)b6+P*%XSxfb@ZaijdpX*c2nS)wF9EZvr#*BV}ldb_i^wA+l$nO^Px zTIEay+foB#$tDuEsyrxcF$Zi>c0<>(JVJjO@OV}xfMTzZ#c9}UnpYknJrcL3+hZ|cPO&L02Hg4ntli82!E zh)eRvwbt7=ng$7pgmVb#CV#hR5Dh8k{`gfBpP0=FPLcwr-w_VipbwN?<8bax` zzvsh3rfHuDON%JlgCeG3udnU*2gsEC`|k-5djPNGjl54Ug+)L`9i(j9maI#Z9QzBZ C(8SaL literal 0 HcmV?d00001 diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testWithOptions_CenterY@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testWithOptions_CenterY@3x.png deleted file mode 100644 index 7e824c2073a478b89c80778318cf09300a374f80..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12114 zcmeAS@N?(olHy`uVBq!ia0y~yU_QXW!1#cJ4JeZJl%)koF%}28J29*~C-V}>;Vkfo zEM{O(v;bj7*J*|cKtY*I7yl3-%>=|C@BxT5pfr#zZklmC@ehz@^mK6ysbG9_>-5?f zO97XI-|oNszESbu(U)8tQJ)q~?MO5{`SVYWo&CR44UB9O2?*lBZQh!Ff8}4?e{P?I zBGJ%T&&;(!yx>1O12d1o0XR``sDX*+7w3z-KX-l@B7_e#Fs)(GK7g$9zyVHXE`t~9 z3wFOPzI_~S08kIt2B2bNB+U%W>O2|;7R+yWx9xncJhFWn2Y`ytAZzBCW3YgsxsGYq zZM*HY$o4G&+RtTxtl0qW*xz@)jXHKTWJi<1Xa)loU8BihG#L!WWbh&U|DTBsEGic~ z4qPzWf~cm&fHfvJ1E+_=-MrKDC!K+S<12Y%bKW;s@e#(KX`unVXx{Yp3ZPOMWh1aedBmx>l6GrVB4Y$#BFq(gO z3`WZXiGReiG+Hl=mIt6t!)Q7fO$UP`9sB_fkpKUmb#sO< za4`H3XfXWkEyq3;a{=Z9|NbwpPXETt)OLc|n7PfLSyXCG!BUN%pMU;xX99MQ-I?y6 zfBrgN5;4U6=jws;WtZ%QCN!{E3H^B8e$L8y61-de;Ccho8wLj^p%tD79vJOF^wEWw zxeCr++yA%?)E7@-I(htD)M11+2ga}lRfWb`sC{$=U?2T@&R_NSS8bx1WI0vjt+RQ( z5u@;|5scFsSh9o+w(#h}MH`PaFvV>C`hLg4&)TX6GaWu{MC;sxI`9kB7@bdFNP>6y zJ%FR@rqTaTR-2xm2J|s0jD67lJKbmkp$KVa44XRR6s(Z{!`r9 z&8inBlH|BPX{-G~Op{3ph538JKj(0ksF32g(I^5X)X^v!%|#8+vSc(DflA@gf^M`f zl7Lo}qjk|}bAfHNMF(o^jkf53ZT!(jH>m$H+FSs21EHO^(dGi4=0fBA*!2P_@L6i; zsNsE3*ZIL~`!9e0FRVU(&k$*;*8l(O-31)rol8i!`bPc%-VM?T=Ga%2S)aXKKkK<{ z^>M@+Fnv5L%l=t$ekxzyicrk+#vIRzF~85>=0B@McI1K6c$T>B_iOrdH&YSGN56UT zEM2?2=kM~$dmGCU3)?;z;c?9R$qM!5Q77Q@^al>q;qmD^ll=dg^UB}IB39V#0rvlK zt)u((TIIz3xnhVl1qK^{5ruOx-)OMoTDmwI>^K%`j;3}T%Th-R85}EyM+=z|UC8`r YIOu*z{y@s-y`VMkp00i_>zopr0KzicBLDyZ diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testWithOptions_EndX@2x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testWithOptions_EndX@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..e4646195719afd7df513e92655ff095e71c83ccb GIT binary patch literal 5656 zcmeAS@N?(olHy`uVBq!ia0y~yU}|7sV07SM1B&RJJqwaxEDmyaVpw-h<|UBBS>O>_ z%)lU~3c`$@K`I}Bf-;#d{vkk`35Y>p0T63IX&{@MciEF~+zbp{H$7b(Ln;{G+&IX~ zY{uJA@Msv4**`119Vwf$kR*y9i1+0+=978V+T%?U71V4QMb zM#H7+-tYhL7=y%m4&VPhon^|gqbDI2-ECkEU`l54ir3%!+4u}d%z&@{eY{YBl(;&` zB@E1^%wi6lJ)9b~d%v7JZvYZIVDV>fy{AKF%pABw7%(03Pj%EGs8KT-BIt>AG(<*2 zWV9R^Em=qFn$g;Kv^_F3TWIz34)8ND{QqyGn)M6V$lU;H| zzRS-X;nq18p6XUQx%Y34{rvUz#-J9hM8bn@jpwi13s=lKko!R{;@fd>8aQydJ3hpu zaX)88!3;)78}vGFM}yi23&!dHel7j}TQUu#xuWLhZ?-fhy|^qYu#%I(K-$JvkuJIEj%lfZ^Y?1J~yf61Ze>VR)@9yC{8q8c(>)u(HO9^ys+5tA!v7DSnfQqp2l1(PQ2byCTt{L zoCvZ)1L$ZB8%6_RG$o8?htV;Vkfo zEM{O(v;bj7*J*|cKtY*I7yl3-%>=|C@BxT5pfr#zw!8Yyzga-K-P6S}q=NCyO-C+g zMFG}>JO3}`{m++wae`8c{@hb5D&D{QnRS4Hna2P^INUy9E6*w-A(HX`B5%@uez*h! zb93^3?k!AQHLN@#yb=iwjBF5Mg>(UHm_wr{| z1TM(P_KGd0K{OyC=)i{6{MN6Nr@+ifNGSU9{nzparnXMrR=8k8<1R+=1Xht5A_i|> z9X|IRp!1{8u(J`{z18bEQXF_b+uuP6;(VKI7(Ym{ zurVSF>qrDNh$gVkfRAZ`44GlDfT7uru{Lq`Q}bK5j1UV;3Z!wXzN_};Udu^$J4Cg} z%_fonT*Z+FA3Oz5!SiSwSm5sveq3C-l15HuE`t}s7sR(k)-7JEi{#DicvR;edgnW%=E-4rPhmrX1JGpA1f*^VaDMPm z0~60LmM^Wj)9zXO+Ts)g0$e?nK~05y#U_h@h87)j8mFsBBWaza_Y8cM=ACjL}c8M1_uFT-+>gTe~ HDWM4f^iQs7 diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testWithOptions_EndXCenterY@2x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testWithOptions_EndXCenterY@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..04ee2d6115b1a54202579e008c896824273d320d GIT binary patch literal 5811 zcmeAS@N?(olHy`uVBq!ia0y~yU}|7sV07SM1B&RJJqwaxEDmyaVpw-h<|UBBS>O>_ z%)lU~3c`$@K`I}Bf-;#d{vkk`35Y>p0T63IX&{?BW42B59UyJu>Eakt!T9FJ?m`wr z9+!h>?K5kgDxL|%YE@=`XyX-n@cnbG{lC-$49q+RAmWbUhnsJ#XXmbeYYG+lBYlCP zit#Jc8K{!uJQ)oAxjRmte{viuBIUrlU}Zlen?ynbBU_*31qQj>1;O*-A|?$|4#DzJ z(`1YnFxqT;xXcbNlEGlwu*?pkS;8XCfw>~*ux~9~;g&t%Bxxxq_{Vji1O=?(FSYQOsDI4+}m^B(_G%SkOuX>$61C%=y;{H8ddSZLN z+JX$3Igs4A23Rn7DX1-YalQNAFUd5J@g39u&(4pk3-u&quK9m?j6tqAa{B*SbKU)`R0!BuU#a=&?QBjBDRy;88S@&LjfFZmHGX|v zw7sqk?C(cU|38~OEk0C;fQ|e2i2VF^mPMquc`~F(C}oy%;5@=2^0(?@wEbbQzdwGe z|Ll8uy%r%GB`Om*5GeRn!yKM8W+jF{bmNaiq{8|jXUUN<0$0EZ3+^@u z1~4TudEJkL*R3{x_BMJtWadCC)-BQoz>3w!;pJ^_SY_DKzW=*Er$%otv|cJ>W^>?d z;nb+DehI5fK79E8PnB`$#zIIPej)DwgGQqP?n4VP{}TND}Q2@F#l zW;9&dJ{{Hy;NY)+A1@RjB@L~R-?H&E2yqAp{Q7nYR*61*`2MdqlUMR%NPPwj6h6fm?>p6P)1YAX!aQ`Q-B>5niRAK2M$bXeBXMIeLA#S<1yHfa)2R&p>Fzt-)qe( zARV@U{}UNl1fb(C4UMYIaSVHb!$gqcyrI#MneD(v{(U98KStku2I+e40M<6V4SBGE z8-uh13>M!G-fej|dqT{UL!d4a#F~=Vu<@8tLq@~IU^JZoGdkV!&I4w>HraIVX!V=G Pv1A5MS3j3^P6;Vkfo zEM{O(v;bj7*J*|cKtY*I7yl3-%>=|C@BxT5pfr#zF1~lUf&>GD*kex@$B+ufH@8mb zrWgt^A2?~BS)Y_4w<7W2jn~aSSGKvFoIn5k^W*lC1_v0Jc@RX+?#A=m|2Ngy|L>Gc zXkcWMfD`|CH4elb_{)l-+`u5wfsw72X_vIUc^#551`8Op4{#YEn+#Wa+irX9sM668 z7!85Z5Eu=C(GVC70X!jafSK(d-@7^$g~n>8JjOdLhKTC=LY~9lsSPYjoDyYk51;!b zkqWP_J7oU8U!T5Dq4Bz~flrPGlJQ%l0~%Bn8ajb^NhCHm`96((V}3qC>SjYfSq4RQSe~i0e#@8_y7M~>rU_ihr2UC z!`*Lh8WtTk5MXxr`~UK$zm2N{5_;zPRB_#u;rvuN|M^#KW_Zt)k!=^R&3buYuXcjN zcl%wAZ{8n9>byRMotMeGZCa%xCNY35Srki!gzRH?TtwJ#fXuLiHrANx99XAWsG3& zKhM!9z*|p@MgeHN314GkG#7xfIKCF=Xh8%jW$_MHjuu3~a(uKP8m*2;tK-pJFq#WS zbHUKh1)z50|NIBl6TkeIe<}U97cp-N?kBrOb|et&OC6S2{;GJ7}kKIw2_mU z%ix9Z1@XMiHH)L8k-9>8z|JDm8U|x{7Yk&TFmUSig8G8poV)W6JyDj2D{o}Qqgww? z+E2Ib+Yo&zo;yHefNn`cbRB^#H6D!v3;Z3*h0E@@oOHKCDCfqbI)2C5PrZ4$NPgM@ z?7{(Eeg@w61bM(mBA~%>e#1MpH~Tmz_tzl0lwv?jajD){F#DALmZ;6%@LSEt z?h~S~9f4;-+pj~p)ACEQPa{I$K&}HY;zbkS@dffg!l4Exo?k2_=84~ZXVg4F3^;5^ zz^(dA>usI;FRo2Pgh1o%24FJLK7fcXAnQO2Bdf$0&KG%y-pw}nd7>SzJmDZ7)!f@7 z_g!483m=wXVBU@=$=+?bYo7RNB0pUDXaXNi;E0?(n!ra(@L^wqA7H=w?T~!tPTQZr P!Dj|fS3j3^P6O>_ z%)lU~3c`$@K`I}Bf-;#d{vkk`35Y>p0T63IX&{>`r`2m(3y`+(ba4!+V0?39_rxO( zJkE|!=YOenYB*UL8~*&{g-NzT3*JBfUH4};BQuY|0R|v(!SF+5S^CYg-0M(*5BUxZ zUs$h*C$LE*G%&JBbVv#?By(T?V`2{#5MW?+SlbVj0ZAvZu^hN@XsaDufW?6^;B_)c zV?smY3`RzSZ3S!nVFHYd0Ss4uLCj51NONH5(T#b187APsAi}WK4%OOUTVMjC){X}9 zXp$PuK%>P4yi6V~94V=RiqtnWE!ZtlZgM9Uw8S_>S>%7CUSEi zm1&H*0>i8W7L4uxel0Bj&tnX#aeMUtKlPrNeSc1a^W%djK~?a91EtJN3pjg(3tp_3 zulj!804(<7Q~l@J)8e=K99a1AK?=A+eXxs>@dC>+PKz(s`S<=#p8;}nLd{S8_^z1W z&sb!n`28T2=Q?Qt2Hymr1@(U~?5=MEyZPAk|FiFJ`LimOiLaMk9a8&W=jCWnGw?gG zaDUy4yY`2{Zhm~a{%6pWTjszps3 zr{TJUL*?{zrR)1F8QYIFPlg3DivwmL|9@t#yFY6t!BC0cC$jU~S;B#AzCZJ4=xM^C z@@eUbt@*$(AP~s=fBK$YAEibxRHo~@uB$C37|8$6=10|CH6j=)^htU;!arCU82X{N uSx4)d(b^Z>U>|Ld@bnC^7Fzwh1N?ezvgvPM=>wa(3=E#GelF{r5}E*4X}v7~ literal 0 HcmV?d00001 diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testWithOptions_EndXEndY@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testWithOptions_EndXEndY@3x.png deleted file mode 100644 index 448ad0d27d8a35e98fda5e6c2cafd63754562315..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11338 zcmeAS@N?(olHy`uVBq!ia0y~yU_QXW!1#cJ4JeZJl%)koF%}28J29*~C-V}>;Vkfo zEM{O(v;bj7*J*|cKtY*I7yl3-%>=|C@BxT5pfr#znte^Fz86TFd%8G=R4~4|b$YFg zClABHkN01G-`HrgL5=xP9J{L0wq29godfkR3=S|bLkWcj)(s44C}u-dZmZo^JE{^A zRHLCZnnIwtY&3Vg7%dq_%TG`RGFmE*mWrdLBCKUKS}Kl~ile3CXm0|kmp0l~B-B={ zIB?*8_ilT&1g6iNH<)g)7$VA$g1ZfWOc{kEW;UFD_bc^zO^*>=Zq1%w=l9S1$tqk? z%cLjFFM<^0>!bw^08P^tF1Q)H|IM8KK)77v)bRh;_usYL&v{1ufzd~YL`3ENU>74} z4wKpjBgW}>zn(t#Qz8{E7g70je!cByZnY1;SYp)VG?044G3E*lz6V&s)E;cwU3b$` zelbE$d;P!l^}CDfglG64NPX0J2;SX3aG;bK=uMx5R3^RMucy!bYv2y-i9 zFre`@8_NdH83#_W#FSmvw|<^H1umEH^lJUTuV?gU9C$5UFtcI-(trRk*cr@l2K)Yh zZ_oYoO|WB}-pS4d8$$rb%XMCk1Yv{5shm6Btcx!@cU%K5ci`0O|9@W3j5lb!PFk?n z|Gho;^XvmPq{Z;h>&E*NnAVdP?Eimlw|;Kk_>;64{=7cD?jTDXX~F*gYkv8;d|+xP zDTbfNpa0XuxrfAHe|`Vmock=#NQ>doj0MdlqZtdO=o~y5tA=Sma3uBrfAbd~r!p{z zwSb0D-`;fOa#j>zJ-GA#Qr`c3`4=ZBrRdK+wW8wvyPsL`dc)v=!|emM@~k2fA{qZL z@+R%)hZj=}%+1OBxwkNJ)v)q}@FEqxE2Ilp!yFnt84s_sd$R_)J~?^uKKBA9E(tX= zaH*``3oe$Q6N_d;R))E{%j4H;`)%pz|4VI{)?j zQRk0_KBy@%ns|VLFq(BC<=$w?18f3}7MzeSM#5;dC6O>%>q0ujjled~Xrp1Y$p+~e zj5ZoZ8x4?h0a#y-HX2474bYJjiGzW1 dc+OgP_1hu&^ZSk70|%xVJYD@<);T3K0RXgVDjWa+ diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testWithOptions_EndY@2x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testWithOptions_EndY@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..8ba7270db2946775996fdf45bea407aa9af589c2 GIT binary patch literal 5905 zcmeHLe@q)?82+xM$Z9JjGUeA+OlDw&PzEHJC{QSdk($wvK|9BfDkAU)KNfUAN9o~` z;?#sK&Q-H0kgbVXSz((-w3NGL>J)~sW({3r6wMg4bQYlbp6`0k`#f)YMtY=(&yC{(0Qkj+3rhiD!2m#_h;TfTIyp()fLcq73V`941UtUi z({lJ&D*(^ENDQdB^uP)pOlT-9If~CLd=Q_0d?Zsde$8!-D7bh6pYw_f^N+SePOI^p zQ_kb$`&{nMS3u$HxK-YGzUV;gyS`2Dm;gH!&PzuD8~+mBMi;H0*BHM(o=FB!1cH{H zmm+{#i|)YSqkXfhH~cXQ7z&S3hyYil?)zpXGLFH^62|!Rsn&^Qg>3 zQ1jF`zQJ5FIVK8bO*?8ryTIL_LQu@hBbGYPArcq{(QvtdI1|3r_q+(ydh=@THc(hU z_{v9}An|Px`0<%0&#^6_M8N6aKEWY2EB$1PergK{f|9}2trNT-8wFoGeO$E-6d{7@ zw@yGks^i8M5c8@)gD|bnYn;#=gLso)H)R?YKoc$JISy8aw-{EO9d69{tTSccs z2H3qx{45nYkT4L?&ha0dB@NQBS{Ibu*Q@P+gEssVdd=ZduBo-Xn%;2I`quflC5oUwt54~uyc^+YD0=|Gx+U_6mxbL=j!baWe)ynL5#GxoO zGT!GE)(!=AyMWds%ad4TZd`60>CUs+xZ}<{_O#nwh`VV?6N<80KFM3F9&_bM9}aRSocN)NrqvZ zUW30+S&UV|O4_uNu7gIOdD<0e+V7ysFBz2Y9nMOn3hD_z0xt7^tDKoYCTP=s7S_tD z<9vaE8F3D&BY=ZmVO`MZC{e<-X840VnM>(yi=|ET>YNUV7|C-hzw9Bat{=$DQ1dWV zM^?Nt%l}+-R0^>)+O#C(e5I;kX}zZ^(nBd%G|+S9aTh2p!qp8;309bv7i_h(X%Ds6 z^+J9iIK4cupDZ?*r6_|Wx6GudD)54o|InvzGx?1?+BARZNsn&8CQ#;Vkfo zEM{O(v;bj7*J*|cKtY*I7yl3-%>=|C@BxT5pfr#zTBz;N_8myudb&7Fa7=RNrR_P@h_yZ?g5 zC=xt>qy-M_Yxr%?Ad%3($Oa=CTNoL6s+e~5&hM2+GKPmEfl;SH5}V50`MIMip+Pko zN~0+Rl9^!nXf$^q%A?WTF`7F@bH`}Oz_e?$R2(f8L9Nlz8ez0X7_AXTYXr<1;m_0g z_G$@CY8wn0+ow5q!#k)Ck{lSK8D=zap7D9`X+!ba!;|1r4h-k_{K~IcSUg?rLlG07 zZo3$~1AE|T1B2KBpn1l^J8a&>yxx!k@A3*9Fkb&pfB)*AxxzPQG&rALcog1!E-+MR zVBNqujfJ$~!!Ryv6OFUyBBtN$Mpw<^zM(pP_Qp(w);-notem1;RmY6ixQrw^ao z%I6L5TQf4+e17%+)9zXK%^G_-Ew;!+A^Pd!%uEpsvq!xJin7tz8cl?wc?(jmjTRY{ z7Vtk<85sWmFK20zXJC*>2MwgYz3JG+Y$(8T@aO;K$G?fkd{I<1sJ^1m<*+o)_WWyg zMoy0f6A%2hS#K|iXr=$jeo#I4%j5eba{p%IC+CAk!D%0u2^tGE16`TQs zbc3owqYsmpcP65i(qZE{Fmv_)r@Lq6djox2bR%*#QuW4jfGq*+ol8MTb=0VL4vfam zXkz0T%{$DaMZsuMU@%$~j1~n9qea1i(V}3qC}18f3Py_p;Lz1*2Vt~TFj^Fh76qe4 t0dORLv?v%Y3Py{9(V}3a6$L*S4!R$bf7`He7jP{%gQu&X%Q~loCIFuRMyvn; diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testWithSizingOptions@2x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testWithSizingOptions@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..1192d72e8d3b6759486b0c954aa34d5a6ee2c499 GIT binary patch literal 6102 zcmeAS@N?(olHy`uVBq!ia0y~yU}|7sV07SM1B&RJJqwaxEDmyaVpw-h<|UBBS>O>_ z%)lU~3c`$@K`I}Bf-;#d{vkk`35Y>p0T63IX&{@YO8rPnFpzfhba4!+V0?39V=jv$ z5A%Vy`(J+E&1|&9pu*zzlO+>AEu3^A>inJGcEe%-yVpWYi0RQAdH=GEzKb@ea42JlNJ0Numlz_?*m!_ve| zu$2ZI@*Nn~JUV}Mcig{Ng3A2sGZgXsOa1!0@Vc{Y3Mixm7+4RiVw%>r^dQLF2M+9GWZckYAO61T zXSpOnWj~j`dFAcA-~LP0igs{tGA&?;2t9CVg9+GW5;x2h7{We2e-*3$Uyq>@sL7D*n1|di`{Q%0?60Xkx>cCPx$7Xvv1B030pZMypXgwe4s%I@)H# z*R&h4ZMH^xV8`PB|2W5kT?`D|jG!LH+nd&tWDI#+4(|QGG+bVqEpbtNo6|iDmPsL@ zub)4^E-zd$|G@k6=hyE~1GON5t>awg`u~>SkF(rUe{ksjz7OBh>%r~6|De|8hb$&J zK7MvcTlG7zQNH@e=YLDztlnSp@_l@j^%i);F~;}6;)fR@&CmzH_I812{k~tZ@BhZ= z{r&5m-(CjqfUM@MFtLHQFz*1H((4|b|2=)v`hS;}?yrCO_5vTQZ&6^%*x%+3?WurT z$)SIKzAE4Qy?E!B@A`XXZ^63_>(m}x{Ez|ZgcJZ9z&pC^-^ZWY_se_wzkf@&J6pqh z1Xo#Xq~xHr@H=1+Dg5K})%U;NJOA|3{rz9cGT_C}j#&-vhZjS;4!}Or1Fe61>NS7A z(vSW1d-^@TxA1B#T=+vq1+-VN1K9nEIXZuR-Sukw>E8AKFWp`!3u~f300ts&KeWL= z8i+$G5dS?BaW-HEcaMO?f)rr?t)brg!Q89N=OMZ0|NrGIj4TKR2gDuX8EP59sSem< zpTWpzuwqY(ibKpG8&(NGvI7e-4*wqaRE{9x8=lT9y(R=fmk6*G9c`njxgN@xNADqqmy literal 0 HcmV?d00001 diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testWithSizingOptions@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testWithSizingOptions@3x.png deleted file mode 100644 index c2bf62b0786395a78fa42272875d4077801e4be0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12389 zcmeHNdrTBZ7@yr+F7EY+&G}kHjM$6N|k~Hl|8jI zzUV26N<2B57@DAP6?_#cTidEg;V#9Zwknra0ShV-q=LeB7I6341d{us=|6MHKJMmb z_ct@&eDnLh-|UOgN4UzS$^Zbak-G3$03<8`n0=fS{*wBb*b6V%w%CXTpuBO~6ZnNp z*TroEz+*0dV2cX^Y{M0)|l8 zboQ1#jX|DuZ;RAj0W|0x4@jM|fcZT(VYmWc>i{N6Z~e1ndr4&!nc!uamf8G4l$4?w zZ0IDhU@LLOO_jOo=;V>Ns9AO`3r=0>UwyT#?;cX8XaV8Xzn0afE+bichE8lNe*%a$Q2-0fLsA` z1t@$&(I^V8QLX@Ga!_Il<=If$5JO2_l%u9zLG6L#dUsc80hsbJFFHK^H7wuVUruN_ zuBmbJd?oE3GCOYER?T{9-m#MSTW#GhBXEUL8-cf2+d3-bf<_=6OtmKmKly@CDGm9= zVE>nujYcuG|0>W7f`O4CQWfgU@(%@R!SDlvCse+Cez~N3rl*-&%*7K^$^f zi9w+Uj%$_N@89EET(hG4fuddKOn2wra5b%d-%#h&xJExL>)T9bsGRBU+CTCdD~_`3 zof=o~=fCW@LF$(wMbBbr8N zHDX3s23n2y#UHIkh}21`5f1%-lRDO#xNMw8*v&J{i0^LEVws@p<@lXkXomG}zy^W& z({_$qMqq@%GlyumVL*BxRAZTvpM;G@Jh4BeHiJF8@Nb%G21>I}f1NCrc4>G@EmI3I z179!w8iULG$@Yo@WpS{d7=zGsEe1L6az@;A1YsH`NGH;^Xl+)}C2qDgp!c9yng~l^ z1qaj+zaFynuuyE^Q^ligrJsp3UEVoo3@rNY-s0Bm>!HN-@W5ml~IUA7}ztTV|kGBaIh)lAN{-CjgPooPKZx{cXQWhG3fx&b0^YhHBA;{ zCbgwy3@pJ7zvULSx#e6Jk$DOIBV>SF240Dj2?pnF&x7&okHSelp# zw$fljz5~OWN9V8Zj{6r&P?>+7=I&pYF1+X8EB8tfk(9@zJE$= zZRU&b?Q#5HCxAlTfkA{}HCKexG&YdS7?^*vu^iC)7qj>E)BC9el|7lhX|+D@-+vcg zFO)L^MKnhPQ$i@C_u)&RFq23~xZl7KadiIb^1Xj{^AJ?_C#dY}(uMcst8A}0gF_vd ziq>c)WJXAVT?S1>#b4J=ub)m(*=S-LO>FqmLZf9VI+pAXK1+9B?u8!UAAz%?SlI{q%+JQEJp4q#E@LuwAzJhjG2;?O#g?D%<=uHos2K z`94ZRL;|TH@&ecpar>D5FKF9WZ^Fu6@4ojZrfnZe`^^BU{dNJ^e(QO3{?F2!*V73r zyH>vU=T4s5|0pey5JXF40k9<^adiGq@0-{3c?l|8`@ZUPvE;9RC=Iw3hz6Vku!U>T zW&e5lrnSI!9wBAX_rE@SZuI3ZO1n1@soh%#Z1;-PKhsZ*-fu!s*|vSJ&z?_x@f)QD zw-~7f_ZQfL)A)BL{?xX*OoGaCYOl|pf0|%Q8clHUeg!mLjwU#Gmti!)0efUv3PN&A zxVqvlr4@{j?ii0j!AVdZP_N%u9>zTnR4Ftx{{J7`#K454K-@vUA&vpu3kFsiGZ+~^ zL>$(?n>XibE>y>MP>;OibuzeD*3g&?EFzM5%Z01%w_I_J1=m1&lE6-?!*)AJH6vk> z=D=Wc?SuDr>Gaas>0oUSazTB?yT2e67R;KvE%(e7O9REh4)X?e!Y`}^*Iht8eLyq& zP5)eado1$qGl=UdfHe+=H3jAizx#T`UTFo_d6TfYb$`k3!m#a?5ZB$qX3ZVn7q!Ac t;-!fo$L>hM=GM_5!H7OegX95w>eOj$zk=Bx00)#9JYD@<);T3K0RRaH8ZiI> literal 0 HcmV?d00001 diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testWithSizingOptions_SizingMinimumHeight@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testWithSizingOptions_SizingMinimumHeight@3x.png deleted file mode 100644 index 802dbc7bca2dee80c03cdc9351e05f58c5884647..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9534 zcmeAS@N?(olHy`uVBq!ia0y~yU_QXWz?i|o1{9gWHpvi3F%}28J29*~C-V}>;Vkfo zEM{O(v;bj7*J*|cKtY*I7yl3-%>=|Cumy-Upfr#z)O*3xVIPo=^mK6ysbG9_)3J-$ zP=Mv&&;QGhe-n@SqNr$4eMO#0c) z^*~Jr7;+e2PYY&-{MuKxdY_pE$xpl^$AM6TA6gt-hT$Cd#0&ZVHJQSXe#&S+vA%{!w- z!DvA}TJMZjqrgVaXi+d)6pR)Hqea1JQ83zl8|{sbcCJVGSV1E{aIES7|2<_KM}dP( zVW2^#x1&Q$JflNQqXU4WSjYMvH>cqF}Tr08K=X sb`VB82%{Z@(N@7|Q9y99P$PeNmf-xq`y!76hng5XUHx3vIVCg!0Kh?)9{>OV diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testWithSizingOptions_SizingMinimumWidth@2x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testWithSizingOptions_SizingMinimumWidth@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..8e9c66caa1d727693187440c6afdeaf9d6c35888 GIT binary patch literal 2582 zcmeAS@N?(olHy`uVBq!ia0vp^Cm0wQ9XQy4te#?2C`Z96^n3u0@7WcE{-7;jBlB-Eog@Q2N^G!DQ@;EqL z6j+=b6dE^gY+Sbk&MS_T%Qt6XQ4(NMRG4t!<_(AN7&vdIPXBgkCMH3SMgakj2RS(l zwDsV;m}$pv^D;Jav^a2Zs1%r)T@V$A^Yl(Xe%sdIz~ZF9!XjiLE&Zaa8_t{l^kbQ` zg94MH0234EoL=6Nqpon?=}#5AN4+;1d!vbS!U3A)y$9EseljyK{Qu8v`QZhyRQd}l zmEPVp?2C2hVZC_s|FYwoip5e&zP)RFu;iiq9;NQ3KKAze|0#U<&Qe!jS2z9N@6S8I zylGE-I6&xlseD0Ngp&f@%J^l3K?e`TN z1ez2CSU7|V_7yVM9_2=;E~@zWxHIhq^< z6g&?6JjVM)R3D-G^wW>G^92+*90fR-SU4^2?`Yijs1>fda;Ht*Z(f8qq|Gmc??I^6 zpME@_pr_ApZu)j`U-|3%mi2SL&)>`@!B+O*7Gslz!2at+760F_Kf12nbp!KtK8=nh z4Uabmfp}jYMR|7;NqCX4)p%I)sJeI>#!(xG#%jshP1{} zKh1TK!YvA1Le{{rD~=U?Z=I^h;V7a~1`K$2%`&gTv$J4k&3V15;=U%gBgZ0zjm$vr zdTk8u%Dx6SD<=HtZ@)-jNV0ay0>dh>Yi>}?W;K{u&v$9vD?jBV0Ci?x(3>fbW|_jx zx*qy*U$7Y5nNyOMi(FsB2{UWwx~}hYHvtm>#F>jlte5Uc^M#oO_VScgm@`McJQ~Zi cPuTz1ZF4pCJ4Gsh%`^rEPgg&ebxsLQ0Ag-&O8@`> literal 0 HcmV?d00001 diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testWithSizingOptions_SizingMinimumWidth@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testWithSizingOptions_SizingMinimumWidth@3x.png deleted file mode 100644 index 6796058c28ee05319977f7227dde29bfc0889eb1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3946 zcmeAS@N?(olHy`uVBq!ia0y~yVAKKP2OMlb5&7_dT|kPlILO_JVcj{Imp~3@fk$L9 z1B0Rk2s64)GfV&q%4E9uhX83NAO?XCK&%0!fo!%*tOcg#Kzg31i(^OydsSvUlCNa`@LaHOypx$fm=WMbhF0}@6|GZ*b^ zWng4t>jn~%jXr_*of;Szn_U|i8had;t;kn&XlOX7-2 zsi_sHB!we|ZEG~p6vl&2KqW>jM$NZ$ITRWi5)^?-B$;M9z7+$S>97H05l`cp1!deo zGZi9$N*vl8(gJp~0?ibFTYGoZ+R;EBDM{-6yPwGi82LnGe(>w?w=%L@TqtnZz;e6w zY-0~|lk2sfHR~1}6Wvmyeo#o~;3J1)j0csn-L5@-_U-MluWAuZsu40LEEFPA&YpP1 zl@;T7x*VuVNQW;)MnGp%T1sqQ-u=9oe4whPqoc-+hTUjF8O;?Wmngp&{4DP*oDf>I R8`z>?@O1TaS?83{1ORmP_*nn| diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testWithSizingOptions_SizingMinimumWidthSizingMinimumHeight@2x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASRelativeLayoutSpecSnapshotTests/testWithSizingOptions_SizingMinimumWidthSizingMinimumHeight@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..ddafb41db79eeb03b2ec449f56a9b16577fa1d08 GIT binary patch literal 1965 zcmeAS@N?(olHy`uVBq!ia0vp^CxG|^2OE%dE!2(!QjEnx?oJHr&dIz4aySb-B8wRq z#8g3;(KATp15i*V)5SjoNHYO32vh*E29yS}nU_brpSc-G7kj!mhEy=VxnkJI*;mxi)(@GA4@I%<%@PS{_t{8h%c<& zXY+5TqJlu900(0u%eiB0yB;aQd8w6q?g|KWIB>KyI54FrGshMR!g$X&+1$(H;BZl3 zadJ>-+`O@I-3~afI8rX(oP|Y6fJsqd!hxGN9KvJZyq!Az+ohS91UVW71Uw$(zXU}knfR2_`sZ~D`ZWzG%? zOo{?bOq_Fic}tGE!g;4ZRqP)1-e~MmCvi5$b3fr{VEF(4kX?H#F#D|rWxu!A4D(_P z1y~R6{l7HTQtd)S;-;BR4|3`cF#Wzb|9rna(|ztgHFoyX|NWJ_F5mc`RqyD>|7(~G z1?q(aPR!r2FJ5l{9YhN4<1Ojxgs1GuPd~opgXe*=oCU!?@SHSLr$4_O?yb$q%yW|v zIX9)UW;Y^B$V$Hu5r!M1cKY#cS$L*L(~q)t zxZAAFE@-O3jq#awe7iN=Z8tYI`WeE@iu6r3`|gf<5n8U18jBBN6t45V*)w0B?Y{J% zbGN?Re~S*g{;t7+r$t;9NHIOX6=n7Qw>?WE#}RI!a$sSc9C+V#Z<>-oV};`*K43w* zZtc>~`}CJNusmYzv<4Q)8&|wv6lW~h;jl-ckR4cbP0l+XkKKwAm z5MVO=GyC3U!<}r*OZad2aR?{~2zFdCSJ66I(ZskZkk`yzkV&z}W2Cz|h#^uxv%XqC-Q&K_!O<2RDV_E87JW91bK1DmW-8 zPtbf74KzGq1CW>?ctYf>F3<*p2q1BSBc-Sx z+W-s1|NqaQa9sy134eo1!ndR4Af%KZO>I<8ZKGA@XoFyIHg|yK;60J0mE3*|TY=>v NgQu&X%Q~loCIFws(cu69 From 6fcbf642c9e8e17ebb236cdfeef05ebc91fc62ef Mon Sep 17 00:00:00 2001 From: Michael Schneider Date: Tue, 18 Oct 2016 13:12:24 -0700 Subject: [PATCH 09/59] Remove all 3x snapshot test images (#2417) --- .../testChildrenMeasuredWithAutoMaxSize@3x.png | Bin 5142 -> 0 bytes .../testSizingBehaviour_overflowChildren@3x.png | Bin 1885 -> 0 bytes ...testSizingBehaviour_underflowChildren@3x.png | Bin 7847 -> 0 bytes .../testSizingBehaviour_wrappedChildren@3x.png | Bin 4253 -> 0 bytes .../testBackground@3x.png | Bin 21094 -> 0 bytes ...zeRangeIsGivenToChildWhenNotCentering@3x.png | Bin 10308 -> 0 bytes .../testWithOptions@3x.png | Bin 12389 -> 0 bytes .../testWithOptions_CenteringX@3x.png | Bin 12505 -> 0 bytes .../testWithOptions_CenteringXCenteringY@3x.png | Bin 12274 -> 0 bytes .../testWithOptions_CenteringY@3x.png | Bin 12114 -> 0 bytes .../testWithSizingOptions@3x.png | Bin 12389 -> 0 bytes .../testWithSizingOptions_SizingMinimumX@3x.png | Bin 3946 -> 0 bytes ...gOptions_SizingMinimumXSizingMinimumY@3x.png | Bin 2696 -> 0 bytes .../testWithSizingOptions_SizingMinimumY@3x.png | Bin 9534 -> 0 bytes .../testRenderLogoSquare@3x.png | Bin 24906 -> 0 bytes .../testInsetsWithFixedSize_10-10-10-10@3x.png | Bin 18787 -> 0 bytes .../testInsetsWithFixedSize_10-10-10-inf@3x.png | Bin 20629 -> 0 bytes .../testInsetsWithFixedSize_10-10-inf-10@3x.png | Bin 17749 -> 0 bytes ...testInsetsWithFixedSize_10-10-inf-inf@3x.png | Bin 17135 -> 0 bytes .../testInsetsWithFixedSize_10-inf-10-10@3x.png | Bin 19503 -> 0 bytes ...testInsetsWithFixedSize_10-inf-10-inf@3x.png | Bin 22932 -> 0 bytes ...testInsetsWithFixedSize_10-inf-inf-10@3x.png | Bin 17974 -> 0 bytes ...estInsetsWithFixedSize_10-inf-inf-inf@3x.png | Bin 17997 -> 0 bytes .../testInsetsWithFixedSize_inf-10-10-10@3x.png | Bin 17224 -> 0 bytes ...testInsetsWithFixedSize_inf-10-10-inf@3x.png | Bin 17135 -> 0 bytes ...testInsetsWithFixedSize_inf-10-inf-10@3x.png | Bin 17835 -> 0 bytes ...estInsetsWithFixedSize_inf-10-inf-inf@3x.png | Bin 17151 -> 0 bytes ...testInsetsWithFixedSize_inf-inf-10-10@3x.png | Bin 17197 -> 0 bytes ...estInsetsWithFixedSize_inf-inf-10-inf@3x.png | Bin 17284 -> 0 bytes ...estInsetsWithFixedSize_inf-inf-inf-10@3x.png | Bin 18021 -> 0 bytes ...stInsetsWithFixedSize_inf-inf-inf-inf@3x.png | Bin 18175 -> 0 bytes ...WithInfinityAndZeroInsetValue_0-0-0-0@3x.png | Bin 15719 -> 0 bytes ...thInfinityAndZeroInsetValue_0-0-0-inf@3x.png | Bin 18114 -> 0 bytes ...thInfinityAndZeroInsetValue_0-0-inf-0@3x.png | Bin 17031 -> 0 bytes ...InfinityAndZeroInsetValue_0-0-inf-inf@3x.png | Bin 17023 -> 0 bytes ...thInfinityAndZeroInsetValue_0-inf-0-0@3x.png | Bin 19708 -> 0 bytes ...InfinityAndZeroInsetValue_0-inf-0-inf@3x.png | Bin 23235 -> 0 bytes ...InfinityAndZeroInsetValue_0-inf-inf-0@3x.png | Bin 17075 -> 0 bytes ...finityAndZeroInsetValue_0-inf-inf-inf@3x.png | Bin 18139 -> 0 bytes ...thInfinityAndZeroInsetValue_inf-0-0-0@3x.png | Bin 17062 -> 0 bytes ...InfinityAndZeroInsetValue_inf-0-0-inf@3x.png | Bin 17074 -> 0 bytes ...InfinityAndZeroInsetValue_inf-0-inf-0@3x.png | Bin 17051 -> 0 bytes ...finityAndZeroInsetValue_inf-0-inf-inf@3x.png | Bin 17060 -> 0 bytes ...InfinityAndZeroInsetValue_inf-inf-0-0@3x.png | Bin 17074 -> 0 bytes ...finityAndZeroInsetValue_inf-inf-0-inf@3x.png | Bin 17201 -> 0 bytes ...finityAndZeroInsetValue_inf-inf-inf-0@3x.png | Bin 17906 -> 0 bytes ...nityAndZeroInsetValue_inf-inf-inf-inf@3x.png | Bin 18175 -> 0 bytes ...estInsetsWithVariableSize_10-10-10-10@3x.png | Bin 589 -> 0 bytes ...stInsetsWithVariableSize_10-10-10-inf@3x.png | Bin 2062 -> 0 bytes ...stInsetsWithVariableSize_10-10-inf-10@3x.png | Bin 3019 -> 0 bytes ...tInsetsWithVariableSize_10-10-inf-inf@3x.png | Bin 17135 -> 0 bytes ...stInsetsWithVariableSize_10-inf-10-10@3x.png | Bin 2088 -> 0 bytes ...tInsetsWithVariableSize_10-inf-10-inf@3x.png | Bin 2196 -> 0 bytes ...tInsetsWithVariableSize_10-inf-inf-10@3x.png | Bin 17974 -> 0 bytes ...InsetsWithVariableSize_10-inf-inf-inf@3x.png | Bin 17997 -> 0 bytes ...stInsetsWithVariableSize_inf-10-10-10@3x.png | Bin 3010 -> 0 bytes ...tInsetsWithVariableSize_inf-10-10-inf@3x.png | Bin 17135 -> 0 bytes ...tInsetsWithVariableSize_inf-10-inf-10@3x.png | Bin 3015 -> 0 bytes ...InsetsWithVariableSize_inf-10-inf-inf@3x.png | Bin 17151 -> 0 bytes ...tInsetsWithVariableSize_inf-inf-10-10@3x.png | Bin 17197 -> 0 bytes ...InsetsWithVariableSize_inf-inf-10-inf@3x.png | Bin 17284 -> 0 bytes ...InsetsWithVariableSize_inf-inf-inf-10@3x.png | Bin 18021 -> 0 bytes ...nsetsWithVariableSize_inf-inf-inf-inf@3x.png | Bin 18175 -> 0 bytes .../testOverlay@3x.png | Bin 21094 -> 0 bytes .../testRatioLayout_DoubleRatio@3x.png | Bin 1511 -> 0 bytes .../testRatioLayout_HalfRatio@3x.png | Bin 1236 -> 0 bytes .../testRatioLayout_SevenTimesRatio@3x.png | Bin 651 -> 0 bytes ...tioLayout_TenTimesRatioWithItemTooBig@3x.png | Bin 513 -> 0 bytes ...estAlignCenterWithFlexedMainDimension@3x.png | Bin 5170 -> 0 bytes ...ignCenterWithIndefiniteCrossDimension@3x.png | Bin 4521 -> 0 bytes .../testAlignedCenter@3x.png | Bin 20311 -> 0 bytes .../testAlignedEnd@3x.png | Bin 18373 -> 0 bytes .../testAlignedStart@3x.png | Bin 19188 -> 0 bytes .../testAlignedStretchNoChildExceedsMin@3x.png | Bin 12972 -> 0 bytes .../testAlignedStretchOneChildExceedsMin@3x.png | Bin 9238 -> 0 bytes .../testChildSpacing_spacingAfter@3x.png | Bin 8644 -> 0 bytes .../testChildSpacing_spacingBalancedOut@3x.png | Bin 7869 -> 0 bytes .../testChildSpacing_spacingBefore@3x.png | Bin 8614 -> 0 bytes ...tChangesCrossSizeWhenMainSizeIsFlexed@3x.png | Bin 6448 -> 0 bytes ...estCrossAxisSizeBehaviors_fixedHeight@3x.png | Bin 17934 -> 0 bytes ...CrossAxisSizeBehaviors_variableHeight@3x.png | Bin 10186 -> 0 bytes ...StretchingOccursAfterStackAxisFlexing@3x.png | Bin 39232 -> 0 bytes .../testEmptyStack@3x.png | Bin 841 -> 0 bytes ...BasisAppliedWhenFlexingItems_overflow@3x.png | Bin 10441 -> 0 bytes ...asisAppliedWhenFlexingItems_underflow@3x.png | Bin 11732 -> 0 bytes ...desIntrinsicSizeForNonFlexingChildren@3x.png | Bin 9293 -> 0 bytes ...lexWithUnequalIntrinsicSizes_overflow@3x.png | Bin 8964 -> 0 bytes ...exWithUnequalIntrinsicSizes_underflow@3x.png | Bin 13240 -> 0 bytes ...nalFlexBasisResolvesAgainstParentSize@3x.png | Bin 3485 -> 0 bytes ...ticalAlignments_horizontalBottomRight@3x.png | Bin 8985 -> 0 bytes ...ndVerticalAlignments_horizontalCenter@3x.png | Bin 10462 -> 0 bytes ...dVerticalAlignments_horizontalTopLeft@3x.png | Bin 8970 -> 0 bytes ...erticalAlignments_verticalBottomRight@3x.png | Bin 9306 -> 0 bytes ...lAndVerticalAlignments_verticalCenter@3x.png | Bin 10295 -> 0 bytes ...AndVerticalAlignments_verticalTopLeft@3x.png | Bin 8857 -> 0 bytes ...CenterWithChildSpacing_variableHeight@3x.png | Bin 10886 -> 0 bytes .../testJustifiedSpaceAroundWithOneChild@3x.png | Bin 3706 -> 0 bytes ...ustifiedSpaceAroundWithRemainingSpace@3x.png | Bin 5741 -> 0 bytes ...testJustifiedSpaceBetweenWithOneChild@3x.png | Bin 3028 -> 0 bytes ...stifiedSpaceBetweenWithRemainingSpace@3x.png | Bin 5621 -> 0 bytes ...tiveViolationIsDistributedBasedOnSize@3x.png | Bin 29836 -> 0 bytes ...BasedOnSizeAmongMixedChildrenChildren@3x.png | Bin 30770 -> 0 bytes ...AmongMixedChildrenWithArbitraryFloats@3x.png | Bin 30770 -> 0 bytes ...IsDistributedBasedOnSizeAndFlexFactor@3x.png | Bin 30791 -> 0 bytes ...OnSizeAndFlexFactorAmongMixedChildren@3x.png | Bin 31064 -> 0 bytes ...ctorAmongMixedChildrenArbitraryFloats@3x.png | Bin 31064 -> 0 bytes ...nSizeAndFlexFactorDoesNotShrinkToZero@3x.png | Bin 29674 -> 0 bytes ...oesNotShrinkToZeroWithArbitraryFloats@3x.png | Bin 29674 -> 0 bytes ...nSizeAndFlexFactorWithArbitraryFloats@3x.png | Bin 30791 -> 0 bytes ...ributedBasedOnSizeWithArbitraryFloats@3x.png | Bin 29836 -> 0 bytes ...StackLayoutStretchDoesNotViolateWidth@3x.png | Bin 2451 -> 0 bytes ...nClampedToZeroButViolationStillExists@3x.png | Bin 1469 -> 0 bytes .../testOverflowBehaviors_flex@3x.png | Bin 1852 -> 0 bytes .../testOverflowBehaviors_justifyCenter@3x.png | Bin 2693 -> 0 bytes .../testOverflowBehaviors_justifyEnd@3x.png | Bin 2723 -> 0 bytes .../testOverflowBehaviors_justifyStart@3x.png | Bin 2423 -> 0 bytes ...PositiveViolationIsDistributedEqually@3x.png | Bin 23546 -> 0 bytes ...sDistributedEquallyAmongMixedChildren@3x.png | Bin 31713 -> 0 bytes ...AmongMixedChildrenWithArbitraryFloats@3x.png | Bin 31713 -> 0 bytes ...DistributedEquallyWithArbitraryFloats@3x.png | Bin 23546 -> 0 bytes ...eViolationIsDistributedProportionally@3x.png | Bin 24670 -> 0 bytes ...butedProportionallyAmongMixedChildren@3x.png | Bin 32630 -> 0 bytes ...AmongMixedChildrenWithArbitraryFloats@3x.png | Bin 32630 -> 0 bytes ...utedProportionallyWithArbitraryFloats@3x.png | Bin 24670 -> 0 bytes ...IsAppliedProperlyToFirstFlexibleChild@3x.png | Bin 17877 -> 0 bytes ...FirstFlexibleChildWithArbitraryFloats@3x.png | Bin 17877 -> 0 bytes ...ildrenHavingNilObjects_variableHeight@3x.png | Bin 1130 -> 0 bytes .../testStackSpacing_variableHeight@3x.png | Bin 10376 -> 0 bytes .../testUnderflowBehaviors_flex@3x.png | Bin 4251 -> 0 bytes .../testUnderflowBehaviors_justifyCenter@3x.png | Bin 4296 -> 0 bytes .../testUnderflowBehaviors_justifyEnd@3x.png | Bin 4062 -> 0 bytes ...UnderflowBehaviors_justifySpaceAround@3x.png | Bin 5601 -> 0 bytes ...nderflowBehaviors_justifySpaceBetween@3x.png | Bin 5521 -> 0 bytes .../testUnderflowBehaviors_justifyStart@3x.png | Bin 4037 -> 0 bytes 134 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASAbsoluteLayoutSpecSnapshotTests/testChildrenMeasuredWithAutoMaxSize@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASAbsoluteLayoutSpecSnapshotTests/testSizingBehaviour_overflowChildren@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASAbsoluteLayoutSpecSnapshotTests/testSizingBehaviour_underflowChildren@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASAbsoluteLayoutSpecSnapshotTests/testSizingBehaviour_wrappedChildren@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASBackgroundLayoutSpecSnapshotTests/testBackground@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASCenterLayoutSpecSnapshotTests/testMinimumSizeRangeIsGivenToChildWhenNotCentering@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASCenterLayoutSpecSnapshotTests/testWithOptions@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASCenterLayoutSpecSnapshotTests/testWithOptions_CenteringX@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASCenterLayoutSpecSnapshotTests/testWithOptions_CenteringXCenteringY@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASCenterLayoutSpecSnapshotTests/testWithOptions_CenteringY@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASCenterLayoutSpecSnapshotTests/testWithSizingOptions@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASCenterLayoutSpecSnapshotTests/testWithSizingOptions_SizingMinimumX@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASCenterLayoutSpecSnapshotTests/testWithSizingOptions_SizingMinimumXSizingMinimumY@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASCenterLayoutSpecSnapshotTests/testWithSizingOptions_SizingMinimumY@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASImageNodeSnapshotTests/testRenderLogoSquare@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithFixedSize_10-10-10-10@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithFixedSize_10-10-10-inf@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithFixedSize_10-10-inf-10@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithFixedSize_10-10-inf-inf@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithFixedSize_10-inf-10-10@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithFixedSize_10-inf-10-inf@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithFixedSize_10-inf-inf-10@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithFixedSize_10-inf-inf-inf@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithFixedSize_inf-10-10-10@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithFixedSize_inf-10-10-inf@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithFixedSize_inf-10-inf-10@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithFixedSize_inf-10-inf-inf@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithFixedSize_inf-inf-10-10@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithFixedSize_inf-inf-10-inf@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithFixedSize_inf-inf-inf-10@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithFixedSize_inf-inf-inf-inf@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithInfinityAndZeroInsetValue_0-0-0-0@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithInfinityAndZeroInsetValue_0-0-0-inf@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithInfinityAndZeroInsetValue_0-0-inf-0@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithInfinityAndZeroInsetValue_0-0-inf-inf@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithInfinityAndZeroInsetValue_0-inf-0-0@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithInfinityAndZeroInsetValue_0-inf-0-inf@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithInfinityAndZeroInsetValue_0-inf-inf-0@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithInfinityAndZeroInsetValue_0-inf-inf-inf@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithInfinityAndZeroInsetValue_inf-0-0-0@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithInfinityAndZeroInsetValue_inf-0-0-inf@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithInfinityAndZeroInsetValue_inf-0-inf-0@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithInfinityAndZeroInsetValue_inf-0-inf-inf@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithInfinityAndZeroInsetValue_inf-inf-0-0@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithInfinityAndZeroInsetValue_inf-inf-0-inf@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithInfinityAndZeroInsetValue_inf-inf-inf-0@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithInfinityAndZeroInsetValue_inf-inf-inf-inf@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithVariableSize_10-10-10-10@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithVariableSize_10-10-10-inf@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithVariableSize_10-10-inf-10@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithVariableSize_10-10-inf-inf@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithVariableSize_10-inf-10-10@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithVariableSize_10-inf-10-inf@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithVariableSize_10-inf-inf-10@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithVariableSize_10-inf-inf-inf@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithVariableSize_inf-10-10-10@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithVariableSize_inf-10-10-inf@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithVariableSize_inf-10-inf-10@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithVariableSize_inf-10-inf-inf@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithVariableSize_inf-inf-10-10@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithVariableSize_inf-inf-10-inf@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithVariableSize_inf-inf-inf-10@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithVariableSize_inf-inf-inf-inf@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASOverlayLayoutSpecSnapshotTests/testOverlay@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASRatioLayoutSpecSnapshotTests/testRatioLayout_DoubleRatio@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASRatioLayoutSpecSnapshotTests/testRatioLayout_HalfRatio@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASRatioLayoutSpecSnapshotTests/testRatioLayout_SevenTimesRatio@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASRatioLayoutSpecSnapshotTests/testRatioLayout_TenTimesRatioWithItemTooBig@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testAlignCenterWithFlexedMainDimension@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testAlignCenterWithIndefiniteCrossDimension@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testAlignedCenter@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testAlignedEnd@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testAlignedStart@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testAlignedStretchNoChildExceedsMin@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testAlignedStretchOneChildExceedsMin@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testChildSpacing_spacingAfter@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testChildSpacing_spacingBalancedOut@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testChildSpacing_spacingBefore@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testChildThatChangesCrossSizeWhenMainSizeIsFlexed@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testCrossAxisSizeBehaviors_fixedHeight@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testCrossAxisSizeBehaviors_variableHeight@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testCrossAxisStretchingOccursAfterStackAxisFlexing@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testEmptyStack@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testFixedFlexBasisAppliedWhenFlexingItems_overflow@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testFixedFlexBasisAppliedWhenFlexingItems_underflow@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testFixedFlexBasisOverridesIntrinsicSizeForNonFlexingChildren@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testFlexWithUnequalIntrinsicSizes_overflow@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testFlexWithUnequalIntrinsicSizes_underflow@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testFractionalFlexBasisResolvesAgainstParentSize@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testHorizontalAndVerticalAlignments_horizontalBottomRight@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testHorizontalAndVerticalAlignments_horizontalCenter@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testHorizontalAndVerticalAlignments_horizontalTopLeft@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testHorizontalAndVerticalAlignments_verticalBottomRight@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testHorizontalAndVerticalAlignments_verticalCenter@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testHorizontalAndVerticalAlignments_verticalTopLeft@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testJustifiedCenterWithChildSpacing_variableHeight@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testJustifiedSpaceAroundWithOneChild@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testJustifiedSpaceAroundWithRemainingSpace@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testJustifiedSpaceBetweenWithOneChild@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testJustifiedSpaceBetweenWithRemainingSpace@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testNegativeViolationIsDistributedBasedOnSize@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testNegativeViolationIsDistributedBasedOnSizeAmongMixedChildrenChildren@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testNegativeViolationIsDistributedBasedOnSizeAmongMixedChildrenWithArbitraryFloats@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testNegativeViolationIsDistributedBasedOnSizeAndFlexFactor@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testNegativeViolationIsDistributedBasedOnSizeAndFlexFactorAmongMixedChildren@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testNegativeViolationIsDistributedBasedOnSizeAndFlexFactorAmongMixedChildrenArbitraryFloats@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testNegativeViolationIsDistributedBasedOnSizeAndFlexFactorDoesNotShrinkToZero@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testNegativeViolationIsDistributedBasedOnSizeAndFlexFactorDoesNotShrinkToZeroWithArbitraryFloats@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testNegativeViolationIsDistributedBasedOnSizeAndFlexFactorWithArbitraryFloats@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testNegativeViolationIsDistributedBasedOnSizeWithArbitraryFloats@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testNestedStackLayoutStretchDoesNotViolateWidth@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testOverflowBehaviorsWhenAllFlexShrinkChildrenHaveBeenClampedToZeroButViolationStillExists@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testOverflowBehaviors_flex@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testOverflowBehaviors_justifyCenter@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testOverflowBehaviors_justifyEnd@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testOverflowBehaviors_justifyStart@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testPositiveViolationIsDistributedEqually@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testPositiveViolationIsDistributedEquallyAmongMixedChildren@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testPositiveViolationIsDistributedEquallyAmongMixedChildrenWithArbitraryFloats@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testPositiveViolationIsDistributedEquallyWithArbitraryFloats@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testPositiveViolationIsDistributedProportionally@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testPositiveViolationIsDistributedProportionallyAmongMixedChildren@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testPositiveViolationIsDistributedProportionallyAmongMixedChildrenWithArbitraryFloats@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testPositiveViolationIsDistributedProportionallyWithArbitraryFloats@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testRemainingViolationIsAppliedProperlyToFirstFlexibleChild@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testRemainingViolationIsAppliedProperlyToFirstFlexibleChildWithArbitraryFloats@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testStackSpacingWithChildrenHavingNilObjects_variableHeight@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testStackSpacing_variableHeight@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testUnderflowBehaviors_flex@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testUnderflowBehaviors_justifyCenter@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testUnderflowBehaviors_justifyEnd@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testUnderflowBehaviors_justifySpaceAround@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testUnderflowBehaviors_justifySpaceBetween@3x.png delete mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testUnderflowBehaviors_justifyStart@3x.png diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASAbsoluteLayoutSpecSnapshotTests/testChildrenMeasuredWithAutoMaxSize@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASAbsoluteLayoutSpecSnapshotTests/testChildrenMeasuredWithAutoMaxSize@3x.png deleted file mode 100644 index 78fafd3fd60416e930e8132281dea76f48b9b1d4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5142 zcmeAS@N?(olHy`uVBq!ia0y~yVDtjw2OMlbk;Cg$dVv&Uage(c!@6@aFM%A+0*}aI z1_nh75N33pW|#mJl*x4Q4*}9lKnwyOfLH@c1KFH4o7l)zlkr2YnR+U2)8eKmmp?pz{rTso;mz{*8};qE{>){XFJG_l;A{KyYW6=G zAKJMZgx*Ns_>?dZKuY8BL&v0Zl?vK6>R5^t;duN!$zGk8XCZ4HJUa+xo$M4P+o2{`k(0)4RC0D z&fW0or>KAfBkL*#jnxx&GI80&GfX+ZzJY;DBY@Q*vh|E;z=NMm3u@|ES%Av57*1)W ztZQI8FV67vv$jG56ITdhK$v1Nt4PH@295dgjEo`y3%D9Kan00TaNskm!_Pll919wl zLK&uno`_*&ou|)m>Up>W1FOgirUh%9o^fe>s9_AS+t0+LvA{u;Ayw2Ud?1~)pY7@M z|NGyBGg~LH`@M1S+%;={2Xk@#nKuoxKkhY(wtS5Z*rfvGSZroyy_Hp`Hlh2FYa;ub z16+rG>1o6YmmT1nbF+~t*VJD4gz3Xs8<@)ySQBf-r>x@yns@GvL*uqt^Esc)D)7C* zXuY9n!#-}W>n*YynA6J^I7FX4&r;;OLk(zngk!{g)}`5p_--^BTL&yy`z)Plr& z358P}85?EqrhH9&aEu{PXsKx<)LEJLqCcPVj_c+TPz{U{mN?*G;4nq-LX!2aldldR z=tXhXr9Io9O`X0+OcL1#3yzkROupLQD2?K*C6)PSwe>4?jZl2h{q}|0YJO&O6lZyS zzBem8?o(6>iVwtYU-S)=XUjuz)`Vw!P1o;vvh@Ut55NIyHyW^`0Xv#vM~i~lYetKL r(K2?l@)~Uw0GnF_R1`d@XZy#{bI?*arYubwG;ZhV>gTe~DWM4fWVA={ diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASAbsoluteLayoutSpecSnapshotTests/testSizingBehaviour_overflowChildren@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASAbsoluteLayoutSpecSnapshotTests/testSizingBehaviour_overflowChildren@3x.png deleted file mode 100644 index 2023ff6ad4aafaad7a64676790ae0ebe2e605713..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1885 zcmeAS@N?(olHy`uVBq!ia0vp^(-;^SbvW37EJbxMS0Ke$9OUlAu%n3g9elavYE95_XzR>rN4W+IEGX(zPY}U_lSW2 zv*XwMTX?@8;N|iCpvnBm;?w-+bB_D7zm~Rm?NHhGWjABH>zgM>iz4_=CswBY|9nQM zJK~6v*v3hs7CP-uH|W(T)h5T*FtU0hxMY)AXgUrT~oy z+p4#-niFK|#8iFntC~O~)?~#NeHQ}zVANqFD#TQi_5yRl|Nq=;Ka>Hp!gWv1(j*UiJOwB^%NiBHE@JOlUDWaF5}-6{}dXDv!#->(`#% z-<#NYG=h`aQ-k>pZ^7E&1jDdH4nkGAvH$K$i$(N|Y8ef&(F8L<`Gt|$UgLtx=P8M^ R8G(77!PC{xWt~$(69E38A58!N diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASAbsoluteLayoutSpecSnapshotTests/testSizingBehaviour_underflowChildren@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASAbsoluteLayoutSpecSnapshotTests/testSizingBehaviour_underflowChildren@3x.png deleted file mode 100644 index d34850d927bba49d997607d013a0a47e354aa03d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7847 zcmeAS@N?(olHy`uVBq!ia0y~yU_8XYz!bs31{C?o`|K}}Vk{1FcVbv~PUa<$!&%@F zS3KP`8#%Hoh$T5OVn!qmLpx_HO{xX+=4HE~*Bt?FO28UT-w2Wq^(c-Cvr5~{BAvA+t!EYIXE7E z|JOg2!Eh_HxphIB6aR8h@&C``x7)29`<~B&C;^t@3uR~AY%~_GvH%wEo&|1AdTYLm zUz57LWi4;L8@RxKd*BS;oS7F612eHlld(|D?zo!wzq!qFvk%V~1ef^M2Ai4F)xHz} ztAa@ndRSs3-s`V1U6vUw{jUdHIoxWTDQjW8u>CSi%LJBml^tb!f86^no^$J3o4qo) zo+(R6V?XEf;vulwP&p{cxog9{_=s$u%iGNUNP;VpEzHI+A1HF3^C);*^>Oce{Tn!) zSdzGR|AuQbmgVODFb3CY8SH6g56-m6`2j0Cp*a&D-1_>c`hNTdoKAdksH#43t)cJj zTOZQF_1^`)Gj9&eUxI;PndiVR<`hz%~ zxPbfh-`1_iOmK$s^>yO+fB$R3=|o5IYrna(doyu{^14|4ec%7G&K^w&qX}U&A&iy? zlANO@!f4e1u7F1q0%Zx|13Lr5|Nkr4H+^7W;L`#1``_L;*vq0Q!0hnJe^z4Chr>m^ zCGlHCbfasZ&#C@vXuzDdAdzidzk|aA6Q2F|HI|%hko=K;z+FLc0Y~nUf657LS!oJ_ zP3Ke=aI_})a@^v|ZB?4>;N&2v<>Z=yCdZN6GAcJ3E-2|`G);`=mC^zXX$U;e=O$?2h zjII`c|LFOHL^hVR(Xx11lSTKv_1ME?^`lTAPGeC3544$rjF6*2UngEnQ BasmJV diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASAbsoluteLayoutSpecSnapshotTests/testSizingBehaviour_wrappedChildren@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASAbsoluteLayoutSpecSnapshotTests/testSizingBehaviour_wrappedChildren@3x.png deleted file mode 100644 index e1f26129efd1aa81f02c5bfdd17663608496e3f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4253 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 HV=Dgv;q`6* diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASCenterLayoutSpecSnapshotTests/testWithOptions_CenteringXCenteringY@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASCenterLayoutSpecSnapshotTests/testWithOptions_CenteringXCenteringY@3x.png deleted file mode 100644 index 8093c8976182b151e956da8fe503b78d47c45047..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12274 zcmeAS@N?(olHy`uVBq!ia0y~yU_QXW!1#cJ4JeZJl%)koF%}28J29*~C-V}>;Vkfo zEM{O(v;bj7*J*|cKtY*I7yl3-%>=|C@BxT5pfr#zzH(ySzR5tk)YHW=q=NCyEyuhV zO97XI`~ELY-I;gcMDJe-i8Fa05|=qm)v2^315ReKgbVW<-W@&PEstzaM1$@Du>_bhum-r=t>?2x z)dIt8G#nslXEYo}!vR=QjFu0Of^{?;M#BMX9gC}+)Z3>CbuXAjhU{m#nivA|4xj{9{(V0+Hs?B34DA(YEncOo3eNaiB@Cz*tiYxe`_6?gjSqoeSWbNXv~39X$}QYQ^b@xOq|mr!5_&uUYK!ECnC9l4eEx5 ztFBB!H-wRlV}=>``|5phpeqn=*xm?r!>E@=V`((u!SnNIUIG_Uqs7B$AwF6!jaIdg z#>i;vVYH1m+H8e2>_=PTkiN=j=VG)Ai0Dz))cpgF!~g%!_F*w_L|^ zLmn5$`~NTX9cIord^cHf#?zXHw@p!3p8x(?^LH|+TYbUk!_Qxn8(6k+T8KwKUv&TS z`;)+aH(OnO(*#Jbd&AxzzyAwOXei!TrZ=lSlTG4>`G?=aEj*wu`z*%O-N0_W|AI2T z8IX?mWkmj5|8JiHBj=TKte;<40f*NTcJZe0 z`bKVi%Jui8&Ahl;7s;r6;EF=-4XiVeLtMfl@c>>EsHV9^GSyE(wPWBbceqM!JFy1~yA?Qr!En(!$9!o5B+?Mv2a zgi!}>HvrAfVFWF&K*XINFz%Y`n08Iy@ZEbx&6C4$^#upxgAZnS((gOfH-ClH w;Vkfo zEM{O(v;bj7*J*|cKtY*I7yl3-%>=|C@BxT5pfr#zZklmC@ehz@^mK6ysbG9_>-5?f zO97XI-|oNszESbu(U)8tQJ)q~?MO5{`SVYWo&CR44UB9O2?*lBZQh!Ff8}4?e{P?I zBGJ%T&&;(!yx>1O12d1o0XR``sDX*+7w3z-KX-l@B7_e#Fs)(GK7g$9zyVHXE`t~9 z3wFOPzI_~S08kIt2B2bNB+U%W>O2|;7R+yWx9xncJhFWn2Y`ytAZzBCW3YgsxsGYq zZM*HY$o4G&+RtTxtl0qW*xz@)jXHKTWJi<1Xa)loU8BihG#L!WWbh&U|DTBsEGic~ z4qPzWf~cm&fHfvJ1E+_=-MrKDC!K+S<12Y%bKW;s@e#(KX`unVXx{Yp3ZPOMWh1aedBmx>l6GrVB4Y$#BFq(gO z3`WZXiGReiG+Hl=mIt6t!)Q7fO$UP`9sB_fkpKUmb#sO< za4`H3XfXWkEyq3;a{=Z9|NbwpPXETt)OLc|n7PfLSyXCG!BUN%pMU;xX99MQ-I?y6 zfBrgN5;4U6=jws;WtZ%QCN!{E3H^B8e$L8y61-de;Ccho8wLj^p%tD79vJOF^wEWw zxeCr++yA%?)E7@-I(htD)M11+2ga}lRfWb`sC{$=U?2T@&R_NSS8bx1WI0vjt+RQ( z5u@;|5scFsSh9o+w(#h}MH`PaFvV>C`hLg4&)TX6GaWu{MC;sxI`9kB7@bdFNP>6y zJ%FR@rqTaTR-2xm2J|s0jD67lJKbmkp$KVa44XRR6s(Z{!`r9 z&8inBlH|BPX{-G~Op{3ph538JKj(0ksF32g(I^5X)X^v!%|#8+vSc(DflA@gf^M`f zl7Lo}qjk|}bAfHNMF(o^jkf53ZT!(jH>m$H+FSs21EHO^(dGi4=0fBA*!2P_@L6i; zsNsE3*ZIL~`!9e0FRVU(&k$*;*8l(O-31)rol8i!`bPc%-VM?T=Ga%2S)aXKKkK<{ z^>M@+Fnv5L%l=t$ekxzyicrk+#vIRzF~85>=0B@McI1K6c$T>B_iOrdH&YSGN56UT zEM2?2=kM~$dmGCU3)?;z;c?9R$qM!5Q77Q@^al>q;qmD^ll=dg^UB}IB39V#0rvlK zt)u((TIIz3xnhVl1qK^{5ruOx-)OMoTDmwI>^K%`j;3}T%Th-R85}EyM+=z|UC8`r YIOu*z{y@s-y`VMkp00i_>zopr0KzicBLDyZ diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASCenterLayoutSpecSnapshotTests/testWithSizingOptions@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASCenterLayoutSpecSnapshotTests/testWithSizingOptions@3x.png deleted file mode 100644 index c2bf62b0786395a78fa42272875d4077801e4be0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12389 zcmeHNdrTBZ7@yr+F7EY+&G}kHjM$6N|k~Hl|8jI zzUV26N<2B57@DAP6?_#cTidEg;V#9Zwknra0ShV-q=LeB7I6341d{us=|6MHKJMmb z_ct@&eDnLh-|UOgN4UzS$^Zbak-G3$03<8`n0=fS{*wBb*b6V%w%CXTpuBO~6ZnNp z*TroEz+*0dV2cX^Y{M0)|l8 zboQ1#jX|DuZ;RAj0W|0x4@jM|fcZT(VYmWc>i{N6Z~e1ndr4&!nc!uamf8G4l$4?w zZ0IDhU@LLOO_jOo=;V>Ns9AO`3r=0>UwyT#?;cX8XaV8Xzn0afE+bichE8lNe*%a$Q2-0fLsA` z1t@$&(I^V8QLX@Ga!_Il<=If$5JO2_l%u9zLG6L#dUsc80hsbJFFHK^H7wuVUruN_ zuBmbJd?oE3GCOYER?T{9-m#MSTW#GhBXEUL8-cf2+d3-bf<_=6OtmKmKly@CDGm9= zVE>nujYcuG|0>W7f`O4CQWfgU@(%@R!SDlvCse+Cez~N3rl*-&%*7K^$^f zi9w+Uj%$_N@89EET(hG4fuddKOn2wra5b%d-%#h&xJExL>)T9bsGRBU+CTCdD~_`3 zof=o~=fCW@LF$(wMbBbr8N zHDX3s23n2y#UHIkh}21`5f1%-lRDO#xNMw8*v&J{i0^LEVws@p<@lXkXomG}zy^W& z({_$qMqq@%GlyumVL*BxRAZTvpM;G@Jh4BeHiJF8@Nb%G21>I}f1NCrc4>G@EmI3I z179!w8iULG$@Yo@WpS{d7=zGsEe1L6az@;A1YsH`NGH;^Xl+)}C2qDgp!c9yng~l^ z1qaj+zaFynuuyE^Q^ligrJsp3UEVoo3@rNY-s0Bm>!HN-@W5ml~IUA7}ztTV|kGBaIh)lAN{-CjgPooPKZx{cXQWhG3fx&b0^YhHBA;{ zCbgwy3@pJ7zvULSx#e6JkdsSvUlCNa`@LaHOypx$fm=WMbhF0}@6|GZ*b^ zWng4t>jn~%jXr_*of;Szn_U|i8had;t;kn&XlOX7-2 zsi_sHB!we|ZEG~p6vl&2KqW>jM$NZ$ITRWi5)^?-B$;M9z7+$S>97H05l`cp1!deo zGZi9$N*vl8(gJp~0?ibFTYGoZ+R;EBDM{-6yPwGi82LnGe(>w?w=%L@TqtnZz;e6w zY-0~|lk2sfHR~1}6Wvmyeo#o~;3J1)j0csn-L5@-_U-MluWAuZsu40LEEFPA&YpP1 zl@;T7x*VuVNQW;)MnGp%T1sqQ-u=9oe4whPqoc-+hTUjF8O;?Wmngp&{4DP*oDf>I R8`z>?@O1TaS?83{1ORmP_*nn| diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASCenterLayoutSpecSnapshotTests/testWithSizingOptions_SizingMinimumXSizingMinimumY@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASCenterLayoutSpecSnapshotTests/testWithSizingOptions_SizingMinimumXSizingMinimumY@3x.png deleted file mode 100644 index d4a15f979b1619e2d08dcc2c4c3280395ee0f062..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2696 zcmeAS@N?(olHy`uVBq!ia0y~yVAKKP3=TG+$lEQ)_<wAm z5MVO=GyC3U!<}r*OZad2aR?{~2zFdCSJ66I(ZskZkk`yzkV&z}W2Cz|h#^uxv%XqC-Q&K_!O<2RDV_E87JW91bK1DmW-8 zPtbf74KzGq1CW>?ctYf>F3<*p2q1BSBc-Sx z+W-s1|NqaQa9sy134eo1!ndR4Af%KZO>I<8ZKGA@XoFyIHg|yK;60J0mE3*|TY=>v NgQu&X%Q~loCIFws(cu69 diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASCenterLayoutSpecSnapshotTests/testWithSizingOptions_SizingMinimumY@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASCenterLayoutSpecSnapshotTests/testWithSizingOptions_SizingMinimumY@3x.png deleted file mode 100644 index 802dbc7bca2dee80c03cdc9351e05f58c5884647..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9534 zcmeAS@N?(olHy`uVBq!ia0y~yU_QXWz?i|o1{9gWHpvi3F%}28J29*~C-V}>;Vkfo zEM{O(v;bj7*J*|cKtY*I7yl3-%>=|Cumy-Upfr#z)O*3xVIPo=^mK6ysbG9_)3J-$ zP=Mv&&;QGhe-n@SqNr$4eMO#0c) z^*~Jr7;+e2PYY&-{MuKxdY_pE$xpl^$AM6TA6gt-hT$Cd#0&ZVHJQSXe#&S+vA%{!w- z!DvA}TJMZjqrgVaXi+d)6pR)Hqea1JQ83zl8|{sbcCJVGSV1E{aIES7|2<_KM}dP( zVW2^#x1&Q$JflNQqXU4WSjYMvH>cqF}Tr08K=X sb`VB82%{Z@(N@7|Q9y99P$PeNmf-xq`y!76hng5XUHx3vIVCg!0Kh?)9{>OV diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASImageNodeSnapshotTests/testRenderLogoSquare@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASImageNodeSnapshotTests/testRenderLogoSquare@3x.png deleted file mode 100644 index 97119f1dc2848e1a539ad927c75fbcb9f5589801..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24906 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 diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithFixedSize_10-10-10-inf@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithFixedSize_10-10-10-inf@3x.png deleted file mode 100644 index ff3ea416c7bbbe79d92137865b4609d37ecbd1a4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20629 zcmeHPYe-XJ7(Ux#%rSLZ!3-}miA1AjMv7*+Iq?Ebk$H)NW?^%CYs)nLsQ|XD9 z-I=5#8zV2N3$&!=lZkwIb~20KZ0Y6r)F-!j%cR|rr&ekkcyp7sHh!j5plsE+yEQx2 zaaV&Dk2*SIoZpr_YtMKBiNZ?xW(z&W>%Uf`r@QnuLYdCMV`jfo6w*xpD!t@9q6qc6 z$Mp5{6I*+eW(%adgwdd zJZ|la`RK4US-gp*o(R^>cTGzA*ObEE!`hXvL$Cc-Xx|e-PEo1*6f05f>z{j5(eD3G#^k|SsjxS^1efjW6!bPgf=7}b z+c1(~-1fUwFgLK0evb!M5>^sc5>^uI2BeI!3gD7p?g%*0VFZMC5S2m%-HUZfL#vp(uK$rm;3?n~5&YhccU*}Pj*PDMKTtW1J zd|D6qV=^{erIcpbA|G~{WbIAohU05zEA{FXPvgkTme20eMvLRs1LrbJ)n{!HSj3mz zuDgq;>kh1*Xx^A*~mN3Q^QquEHu?X1=qH!fLNXmBUq76^99Xc}pCnLY4-b%2(EyMDBup_2(M5pWaH@5{B?D`t01|+NDLfzr zbYSja?*7~{NEt|(Pf=8JNJ2? z=RGgGU0YqD)nsc3A=;`+a~&bd0eYxa!j;YH?NZ^S=&q|MBaWHepTd_tU6qa9gybEk zhoXGwh()-V+itF@7tV}u2p`2;p~#ocw0dXQu`>7a?mJeeGz~gF zgx5yQIcIe(8Nq_KKi3v#oeE{DktfljYnIR5TKMGqF`Z?xD^z-^@GtT#;bLFujo0m# zwClekp-@QvxKVA8Jtnm4%pUeGo}6&IOQR#uu~HfJPS4U9+=yy9a%^un6q<=yBDA|n zn5YF}JO4AT_1sqqW98sZ($nk{+U+IVy&lF-)9IK{5_H^&AOpYmtE zUud0oc?)Iz3L{J~^X@}Ay|x7FSgyg)_psHQ=8W4wYY|OLc>MCW0F0J?n*VL4zq)+k z=bTE8S+&{cN;-4;6W*DzBIBBS<9o-f9FCrH50+j9+7iI#gfe6Dj?=S_4l##%3zm)K zSt3r&+5D`_WZJ^ zAnjK=^Rm}Ex*7Kyv=+=74tj!*Iua6ZCOM8UGNPGk{8(%Zj0Ae-9!HaGXqt~oktE;u z=Gia&z?H$dCaWxxrPn9vWcfwHT0Nu8c$3v^^~n>AEIKy6ifOG_dwS!d&DSH}ZRboR zF_f3kHc T|LQ#l{oj+S@@liA%yQ!&BrYX| diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithFixedSize_10-10-inf-inf@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithFixedSize_10-10-inf-inf@3x.png deleted file mode 100644 index 4367dcf7de947a28a9ee8076db7e4cee4857350c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17135 zcmeI4Ur19?9LLYy#=Miwt_iWF*d&W0jEN#j3Y$$-N(&LB@XsJ@hC#wIM^-ppNe@vk zX&Ty}*I=3W(x2sA4?&r(M5ck@UTm3#QKE0b*zJ)GabaQgG!9$|ekX8S7^?tLfAZic~t*7z|L2K#Yl+nsjAyf7dY zj8)I;nLYaMJWb~MN&8%@l|576!R*m1&g9-$z8z@w55%s{DLaX5T+1`KIm={j(hjDFATrjP`<~L0JV%?%#ol*bvDKA}|zOyUO(%U8%#p8uZH zVG)e6fW5ett2w+Dm(yV)o3lvJDcq@uN}(w{eG))`1Rw!Oh>pq_kf|1c1Rw!O01}v0 z2#^3I00}?>kN~d>{8Q8y2u~i(EP;EG{sIn;Sfv(701{~E5J-@sL_h-70+0YC011(7 j0?ZPmBpV>%FCZZyePlZG!)1Mn_>UCjC6#7Zv8D4Dc3mCP diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithFixedSize_10-inf-10-10@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithFixedSize_10-inf-10-10@3x.png deleted file mode 100644 index fe07dde6ca65ae59df67dfd5b8f76af1e01a3695..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19503 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 LB6PT9FN*pnt@Unb diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithFixedSize_10-inf-inf-10@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithFixedSize_10-inf-inf-10@3x.png deleted file mode 100644 index b2c041116d50b10172be628cc8cad3fd9b430a23..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17974 zcmeHPZ%kWN6n||=TbFh%@xw|5`Y@PGqf0Rm_6M3*>?|Y>=Q5d7M~iW&Ba>!W+HADY zfp&h7Eq>S*9F_&+HkmO0g+ye1S(nUY%D;hxgqHS$*a6$RtO%`T^|qDvw8pQ-nA7C_ z>CNl8=bd}*@0{PgC;f1DwN|`AzJa1BaaE;e4@L1hVuz4VT0+&)9pu7k+M}(Y`bTna zlP`}LD)%>0RKeER!P$AbNKYDb-_g9dmt48zARo>(a@w4@#_pfsvRghUT@;Q~Y1Dho zoTV9c=j-Z^pHt_TH`X5SF&ZvCJtqEWX7YL0rg?E>sYT^bL@#i7A|*?$pA4f+S$J5x zGVeLZ;mh=Gf1Mu6g+dxUMt)E#zV4c9G2grE&PhHd)6-HWB`kI~TP&5dKJX0>nci9# zM#S0}Dx=?9Oj+b-`^sHUH|&?o$%5Lk>@ME@K&iqrbj$>_lL@n=sN8?ia)D9Cdi8;$ zad~v`VO_L8I#CCmV6NV~!_giJ)!17W6~EuxZiQpIdYIoLwe~~~Z(fVK3fKLUxK#8; zo1{X~q5H$pkQa(>JJM~ePYN~X1l0caF+l-%UX)wnZ4dZePHREHB zM3eKn_S7_z>Ae?;46VX5pfXvP@BiZIN_xBZAS*a8sc`avf-L(IPbEC5iY#v8wyrE@ zgSRq?R_UPHKTRjqBa*frVg(HZF*Wv?U*AqyDTaIR(%fYx>~}#A>f?XC{iiM3o3Ksv9xwZ% zU_z^a!~06fsj0f=ZLh*Mea~YjnDSGqFa$vM3)|(5-`pI3Hs$N&&dp>k*n;DBIHon? zH;rcxbe@K7GC%+E-IC8vs-Ul2IYjrlmX3T2+gPSlYCB3>f@!n*W#0b0`ZK);!JOjo zzqbh|dAEBd&}?W*Fg$2V;MM4rAf>_y4nPC365u?BomAMeVb}rL2S)HzGKI+yz)#F8 zL1e`gJ%yi`qC;kbY$t`ENE`t(ks${MydIY`0BGQH1}=(P!v5At8BV6q0VL*sp|@(n;(91 z<6<`Vt7elU1ZEe>Km0jo{losQh7s6>(`KW%5Q>#!#Y*2NKI3#+*%3dZ?1;I=b~Ju4 zeITvqNS0Z2w2SxX)tp*WT0N9LvmUBg{K9Iz*=65`1sLc+fS34-#$slt7lPrG7&>{7L} KTGL;lKmI3Te*YK% diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithFixedSize_10-inf-inf-inf@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithFixedSize_10-inf-inf-inf@3x.png deleted file mode 100644 index 88d16405d2b71a4dd48f0824b4dfe3017e97e34b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17997 zcmeHPZA@EL7{2Y@IzDcN%7X2HSp^rCG}?v+gqhhwSz!*`<`PGQt&G7~aD|K_j0kea zhoEj_(dc9>DAWB?ie{TKsN7W?EJGMfMNyz=L~yQF7t>a=)^kel2gbkpL*FL%-uB#k z&OLe0^FHT&pL5c-?YTy2*t#%+Af(w@hMfdKHsK>gf=ax({!Qp2s@!QzCwj(Wm(Y*U zimbd!g1GNte26k%)tFFW>_NlhyU)C|F%dJibq*Zn+U>q|M% zAd<*U%O~0|5sO2F&oRt7y2kVA^KR$t8U8tuL@ZhbkNv+5@?=W;T#>K8Hs!g&uLB?o zSrr*TSpE#7>1y=a{_ajgM0$(W{N>!ZnxtZjmBu^!2JflG_@k>8F8#=4zsj4c(lAU1 z{f_kF)X5}-Sa*`6(N$mmW3Fu@La!^1l>NTx&8jb6N7naritcUdD!caXMFd91CLJQ@ z{-AAEcX0!~n%o?cy0^j{{{yNMN_vMPeoHDW#xVDsLzM>VZk(R`B!;BExvFz&uS5@D zMXvGmI+y-KuhTixkKb#JX>GL{Kii&xy64!9nmci8e9(tqR3#nyuE71vz?lzi>$!wZj&%`MafoOHd$(b)d7vD1^%iEVvI z*=<>yqb)=Y_7pQ~<}b`%t2^=#?#LsOZ#84L<+Jvu@N?tHxSsr!Sqtv4oF6C{j(=)6 zI7(ej=E)D9Eh@o=57I0eeVt(`v7^+^@i7{saLN1X$t}a9!ZPYS-8#8LJJBSp98K*n zeCyb8>;PPY@={Xv_Sw?zP?q3PgOo}>V$X_+OA?l;uS@RVYMd}c2`lebw>O_mPAd_X znck2ZUOCDNP50Q^2 zNA5^_VMB*t9%7iIwCbhv6B_Jse5(Rnv#lbJ21By*G#HWv3m}qr9B^%pZGa&NyK-lF33J`YL*b;h}ZdcJCE#qK7_Uv@X?ZZJ*dEmH;6+(eCDAP;VL;qu-bGU_A6 zp6VIlnzt!ZCm0&k6|Hoer=(`4YQ?rIJ+X3k7IX?MwTx206xv?`-bbl{5`Yqb64(VP zpag^kpah@7vw?4~nW?)db?djqeQo;D4{q{jl`Mf39OVxi-gf4 z0o*njZ6yF(U!z6BXpsPEgpaloMq3G^tpr%Fb+nZ*+DaI0CBTMfMq3G^t%T850&FmJ zwBs<^ae$+-5=L7Iqpbw^)IGh27ugvY{{NSq zGMfds+~FQ*nZw)b8+(s92rwVyi=BD@v3aLqgg^@a0loC!``$m_j=Ef6L%PDn?~Ah6 zSt2hY_#@51A^^+WkV@Z|nR7q-0tE#Q1-PHVs?B&+{$MOnP-p-TwZVxSCKEnjteR+I zV1iYxV1)^n9S&ivn&4pK7`HgcO2FUeEA%CfJtma1FKE~BX_NB_BD06}+`ZKF_SWriBOtDB+Hiv zI8sM&Ok7PY-#?!>2W5Z$bhceK@67(7?EXJ6x3Q<*eBayL^TkT diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithFixedSize_inf-10-10-inf@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithFixedSize_inf-10-10-inf@3x.png deleted file mode 100644 index 98a3f5faabe067957a89db6e3a0f6ca51aa7dfad..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17135 zcmeAS@N?(olHy`uVBq!ia0y~yU~U0n4mP03Prv`xK#H+A$lZxy-8q?;Kn`btM`SSr zgQ5ipGrCSQOaKbXWV-l=0BI&51_H)IKtcmTgV>7vw?4~nW?)db?djqeQo;D4{q{jl`Mf39OVxi-gf4 z0o*njZ6yF(U!z6BXpsPEgpaloMq3G^tpr%Fb+nZ*+DaI0CBTMfMq3G^t%T850&FmJ zwBs<^ae$+-5=L7Iqpbw^)IGh27ugvY{{NSq zGMfds+@Te;%;D|zgS|`+JS+$K=AN;fYsR7M%lXkPXS)2m&p&Hw_oA*B*pRMp@%y6e zb(YAh2>wWOun53%H>B40W#-(EzCuBPLjmq-uxc}2l|L9O6cif3V{LHahRK8v7|SM_ z7?@ynD_CK|Wrsr;%O*IOI7S^c8dAW)>(MkNkuaM3fF;vtkpL_%M~j5fA^}`$jur`{ zMFON5HCiN$773$80=VlkS|p4X39xSCXvYDV7DihMqea4KkuX{$AdTIP773$8!f25& zS|p4X38))2M~4?jhZn(}$kC1i(H)0%0$=w2jQJa1tSgN&r#P!|UEPJVmN&k?`adiC zC-P3`2iJK@zBbFWOnZ20-p)6Mh+WSgfZ_stPTm!%=VQLXN@rkvRIu%;;$UB>x@S|m zUNzEoYa8ZR+m_}FLUA{Zr`tm6GqA3CjqBtNIc9LKe>3y69Fn8XJB0H;RM^rI{_RX^ zKRBKtk)6I^b$fw8)FJKaXPb^AHh~{7zHrsqf8A?F!4b0#VbXi^FNF_ ze^`dTO-m|L#R!b@(Rps*=<4W-0N|cNY|9jWFc&9WRVg*r_W+$p;pyt_5> B9OwW5 diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithFixedSize_inf-10-inf-10@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithFixedSize_inf-10-inf-10@3x.png deleted file mode 100644 index 79c1dd46be85bcb7fe5668131724d5b34049128c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17835 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 diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithFixedSize_inf-inf-inf-10@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithFixedSize_inf-inf-inf-10@3x.png deleted file mode 100644 index 4d863686b85f90581a179ad3263e990ffbf84ae7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18021 zcmeHPZ%kWN6n}5UN2N5aS+cflDRf!P5``59$YeEbR|FzsZZ7H;kakNt{&cQMSwNxx zq(yWZ{o>LM76ja~EpeS0Dqt*c9pVSeC~l@>qn3Vfsd1Z)%|;QV-q)^umk)k5F*!}% zpT6|nbMCq4{?6~5d(-z{sjK4W>~({gE_bqda_iPs6ZFew697{T)MvL zH}vI6WAymWT?=b8s{I}0 zy*X9Oq*9o5^__8xXX;3>lp}E|UcMulYU`Ydt#tWpBqi2nP7#SK@?GR~>ve*YE2kfy z5)`$L%YH?7${V!fSWlp#9e-DxCCt2%{Pk|mdXMDI_Mn7qU#k@=)6J$@EaBJ2^&P?E zM>0BSZFUtwV)Aq4{t|h(FMK?323M9Mvp^}Zlo))9nL050kQD$D06dd%1i}nJLW-LJ zBmg7;B&2yWumoTUNnd~z3xx+@3BVG7C8Wzg00{sIDPI7V04xDmLMk!A^q~v%Gb|_rhrC!h?#3 z+8G5exH3JEgzgl6e?#)ZF=@_Ly%%5Oe}c0?%?p2N4Q#Mn?W(d?v(3F#rj?Bd4|4HU z{DKx*E#_NepL)L?8!BcO^rIh-*{&-vr-2UBd%>F22yUN|4^p-3c@XGJ3fvE>4@apL~m-iwp333sUq zgB1e@oCcLhHu1#|{hN(vcFx3N?hw{A>T8E(DKg-;EO(U}0#+kyJ47C*ZP|l~!;ysR zxr}~tn%>KiI;yU@&8MP^@q@TJ%hXP;f@@x@`!IU=anItzU;lP*vzR7!WQ;(cCIxDN zy0IGP@Ad}@(jk>GXn70W9c_w# zwQc>XwDCv0PoEtvxKA$1^lQvs#@D!}<>Qexj(n8UEEp9OXH3Kl_2uRQuc2qQQiKa@ z+F0F5n|oP*MDpyrIZx@ge^@k*Z)8#4QQqb}*yUrL2HhF*dgXn(wpnM!Tu8Os)K5}l z{vlk7R(nI~n9ChLQG{F3U-ro(+p>^#Sw>zTwb`c^H?--nPTIe=k7Uok=fb6kZ{(hQ=_#F}MS)#C9t}*uf$P zgdJ>}Km^B_29P0angFlF_%Bd&Y?=T?#}XFEcCcvzi6fifLJp1>8larPS_8@%YyuDE z42*I?kqygCXeei3)_`&blrsP;0V`o`2bRg0l0W3&kb}eGEmnFEL%kBS2GlE|UMc^- btnFBv_&;ySSMO0U{{vG~S*N+A*1r1>dPde= diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithFixedSize_inf-inf-inf-inf@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithFixedSize_inf-inf-inf-inf@3x.png deleted file mode 100644 index f517f65d5c7d5824e19505efe73e6c3f564ef4c2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18175 zcmeGkTTl~MbmL--l1yVCm;}V26*~jg1S*M*N~ADoq2OzHD27y!m=O^P*5E|VY8*wY zrgnq@5wRVdsSln`YpKzdDi1A$+Oa|v60Ak7h;cv*BGP*ogX?EM`gbz3ce5vV&z?Q^ zyziOhE{=&5Opr_<2tu%EVfa#lAT9XdaS>!7W>|$z9K+JcFruv4=K;DHpSdv6KoEXP zd~hQ2kN02F`aiD!*5=IO!7*B9BjHd*X044!Uf;-TJ zC;_5`5m|u50TKsD97a3?Bo0jF0Zamz1TYC;65PQeBo2@`xMcwn2S^+saTwj8f$}1h z7ooh!1d9+QK$P(RMhWpjEkla!@rB2$`~BbC7^e^OU!+a$-c~C9c;ALGZ+hsYM)NM~ zy?~rAyo$wI=MnDnuBO|b8F<&9iWOA|v!0HRFKc{{SIBK@)7fWD8Lm zf))4{CAy_v-)U>vfiNiZDGyb=%+|LW(dH{i;7!rh<`ytcXl_c0ZrfdjOpdLPPaAqw z`?SHnbQ7ZID?#?%-M#4=U*=tP`~=>doVr{`W-XdISJJT9clT=lG<;EX&AiK%WILa{ z1!Jj~TSfJ`$9H)l`sj6tjPj=a3PTERl;|f3VtDv-K}!QcO!vZF7LQt^GQ5|(`^kb2 zSE=$lEB!4cv7sl0scEfu9@J2(AKNoFZ=cO{Qz+ZiJ&plGR`9X*CZ>_$g*T5UWnQ5u z!>KCY`DDt;m&*zmb{WYzL;1up$E+%bMH-&i^%#+f$T4uI-Zpe*|F$2^J9mIH%W^Zv ztEaXaKcP8D_*VDnaa}n%8a(q`^y9(Ll)qXq#uB-;YoAFF&7g}9aUv!K4EDA4r<$n% z?}o#nMfNTuvj!4U!<(Zo>X*b|@rWcR{w3e*Ux=yHiCtmF-+Qx?izgvUGAENyWM#dw zxt?~sKE`JAq}qEmPfmDaDpA7-W|r2Ojj)O5w^!KhGLmn)roQlW=TOpprn^M5hW7M} zDzCabSaF#kFQ!Q^hO}xTaYsovdeFIlqT9dIT}4->I<@6x^xC7FuvB*FXwS~UKeA5E z#1g(<>g#$&J~PcrMhi0*6FxllUPuK;n5hO&_8H z_g7xo7{oX&_h6&;+^E0)X#k#&DaS)XkhN6)y)uRk)0QZNmCqAa=&vx#@oI?TR((|G zRo}>l@%y+_x84bs(5 zE6-lv`x+yMo5xSpe>wBO*KC;Rz99Vc{JgjojGnzB6qpIjWK;+w)2)wKXF$zI%@bw^ z*i5jQ*foL!0&mU)4iFl#?IXmQ5N9&c0|f1C`v@5jq?1f`1-UufK0`>0ohbdnt|!L|kL0l|hE>`uN85+I#q+eb(zM;#~L^oJ50l;E(t kfQ}A#XUu;s!MVn@T5i05Xqx>X{)d`H5i#LqVcH%40i_@% diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithInfinityAndZeroInsetValue_0-0-0-0@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithInfinityAndZeroInsetValue_0-0-0-0@3x.png deleted file mode 100644 index 2dc72883af8e0dd01d3b8027540c53333c364713..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15719 zcmeI3F-XHe6oy}7)mU1oYbm9IprhFYm$s(1S*nySZXH~tC_)!S2dfqA>fqw!=F~;e z!A0F%9Goh+i_i{^q7d&AD1|x~gfDP;m*aB7BmDX9y?4#kVm=yJl{WJy+yKp6Rg-t z*r|S-y*G5{J~b1(9*ov6)7Lk%{(8M>e=M@cA_I=aCxagwKEWsG2^y>ZJ4gXifD|AF zNP!uGsM%$(^U}Lfr~oQ}3ZMd{04gB%NIW)(Q9}h#0aO4LKm||%R4_a$*sYI?c-}*@ zeXA1BRh@Y5l6EFsM^ONU5`OUrU=ElA=72e14wwVx!vk{=6a)o9K~P=iP4NiDBNUHN yJc1Mm2nvFdG4@YuK?P6&Q~(t~1yI3%JJ+ky&hPQpOvLVd>XXoJuIRL~mBU}4JgCtC diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithInfinityAndZeroInsetValue_0-0-0-inf@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithInfinityAndZeroInsetValue_0-0-0-inf@3x.png deleted file mode 100644 index 2e94b4f983891efec90dc72bbcbede9165c6755a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18114 zcmeI4KS&!<9LL{za-<=L=axn(CoWEsG>8#9B;ov%B}Q>kC?01WG$^8!N(m}aP{F~a z9Sh>BnFHp+NcTT&GEtAEQ6FGkyY#)YVfxkYLD9I<6*^`ORo!jtzOU{0^775HY^zdMqI*L5^J7a_BY~axr^5c}>wiDZjWTC%uKDlC zq}lwWlhfzSLMs*S1ockq8uZBG;J=vIu1FN{rB_Bl_ctXYl+enfw0kF`c~%F zwVoO8JaNOH%o?5v0+#OE{&ljJ_-=Z4WX$FdLOb5gbgKFA$BFDx!@PIvk1p?>?y$Vl z@4>ehwE6GdS}vx+g@w!VgEuuy1Jl4XFb!}Nn8(+^QDAk41%`WoQ{%hL)jaXc=0DmY3Bo=*nbH5y`+C@CLjAZ@?Sy z2E6g4yn!$kSud(%bhG~z?>yVY*TC1n*TC1n*TC1n*TC0634js+B>?HGB>$3|Om;2V owL#MMIrKo|Oa=l61P-1naF81|#-bI<<)M4XOsXYq6_R%T202eUegFUf diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithInfinityAndZeroInsetValue_0-0-inf-0@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithInfinityAndZeroInsetValue_0-0-inf-0@3x.png deleted file mode 100644 index a23456fa40b338b38a6752250a5ada956c2089c3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17031 zcmeAS@N?(olHy`uVBq!ia0y~yU~U0n4mP03Prv`xK#H+A$lZxy-8q?;Kn`btM`SSr zgQ5ipGrCSQOaKbXWV-l=0BI&51_H)IKtcmTgV>6}JM@@xfV8})i(^Oyry$Lp3yf?u4P^mpT1)@+DZg41R ze6evaE1Lcd4crUSHM@v+$ldlv*a0mdKI;Vst02@1^ A%m4rY diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithInfinityAndZeroInsetValue_0-0-inf-inf@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithInfinityAndZeroInsetValue_0-0-inf-inf@3x.png deleted file mode 100644 index 9def6b5706fcf9c3aada87f8cd578e64b4d61c5d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17023 zcmeI4PiWIn9LHbUE&F4t86M2)4xPx*TV^*L?$V6Tt*BGS5QI&$i`(cyVQwu9}uF-5CRL@IMzy@&&$z9dWcdJsJ6TM^)9@Uppp0=#CwJVZDy^nSMRyqG_s4{U#Vwdc_1^%N)-0GNee3W#^|YkJuRa zQ6=L{vMmSge0SZ1|Ds=HLKUPaKU&!0bx6@?*|-u{*zi@+87*uP>s4|0%sBs`Ae_)2 z1N>YV4g!?_{tRlJ#ht~LU`&PF43~Wn?v5|97fCL4t!YJH8{unCxhIwqZbmSgE5s;` z{#dVbIQt}}q51)D^r_Q3XBOg(tat=lDT2b8qHKev1Q~Z91qhHpQ41sh z2}X|#BmfDfVFD6>1R%l6FyIp45)3UMaiHA;TmoDIT!Qr=3rGMGOfA4Az$L&Xm^}kr zf-$@XBmfCO0+3*tMI;XYCvn(7NG_LLzJ7-g*BgC`#NuNb4AQWmo?7|EqeUy zTvvb{rk0At{45M(?|t@-QjKmw2eBv^Cf;S%5yOf4XB zK;nSJ!R#53I2iA00SQ0?kN_lDW)X=45(i5QNF0zjAaTgQ(*Ca>FP6lrUv2f>KYvL7 OhX`MDn>XI1p7{-F=syMk diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithInfinityAndZeroInsetValue_0-inf-0-0@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithInfinityAndZeroInsetValue_0-inf-0-0@3x.png deleted file mode 100644 index b4fbf19ec1884fad3749edf85332d0561d443868..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19708 zcmeI4Z%7ky7{~9L9#c13lDMYOBs3|q4H*gj*>22#2xg+8nRG79OhHR1gTlEjQqgy! zy$kJ4l**t`L&-VKS7AvZmFbk;6f`vyG|k!Xwt2TV_ud!Z!QE~9-R^mIzlYy_?s>ky zYc0snRz_>0DT-3&=2!|TO6KGjIYYkro4sdc={=rSx_RHbv9`h}bZ$zvw{lOr*E;;?ww7n+7ko!J8_lSLtHnC5)8UnAZF_qL ze&e3CY1cm$8|N#oAP zM{&Dg%+}mbv#IiaHr$xXpp`#6Sl9YBO~1V27hB>Lax;5VX%*~nArCfVYMgbhHof@w zT;vduJ%$$15Y6;55f$r8r}T5lQ#$X&a_?JHjE%oD49*nuN zHkp^|u%0ZF*$Y%x9ASny?Jbik>*zx4t8(ji?~WKuX=*7C;%DVvF7CS6lU$8d$dp+J z^V+vZjDid9NGT8e9?eohpH++)MXgdIWDv9nS_CadS_UJnaB;>+3p@ZGfN8e0H;>{1iVLJ9f{K_9cmO;A9t5un zC@vs-5Ga%b4}b^2gMi)yf|>nMT;SrIMj|KM-L0x0t){3H1Fs?TK|vN$4?#f&1sRXA zP>@0P$m?bydxTb(TpD;CG_<H-gd2f%}1mJ72YfCqeX15X|P+MD?&&L0Rc@RPHWYO)m6j-p%Ad5kOIm>(1ZcR zRxMo=P{PZtMeBnUeDX3ti$EYSAObC*R1iT5$V22&*mJ+>zpy{-%ykAsxZiue=kqz| zo^$8Ux#yIZVD0^!xf9w2Q0k;nRGJ_@mu1^pQ?& z*uaLj3^WT{x;=RVbItjf}YZA)z|tozt7H%>9SYAbA>5EaU3pR>kD}<_tPKsqv^&Ed32;(1}`7 zEDx-z-yQ}}X?ZvW>t|G6*VF&~C$wUdb?s2T=%ErDG3m9c~s z_0Du-Z=+eauELU6^)!aHd0qX?beVgNUbV7&~iSWG_6-kP2CJW}kOhdHorrCzmBcIC)+@isZDu;gp=b0D|2qqA`7q)F1- zXi%oTafkzyl^KhxqRp=R|H;>Am;hh(;A!_eE+Gmfhu}ZE+`D`oqEGWF!_=d9Pu%4C zUXX0XxIe@n{lXbd7XtbxBR%CWb3orWJ))#H$5Q#{EMbzmLy;^GUtG}UA;6*BhHLwC zN24Bs&I=qh>!M)^g^U->O*Cgp!Xg4eOPzz%(yfpgS-=DU`58)^>w5y`TFnsStJSPK z7vyVAU_ha?U<}3933v`jg6a?uFj&7a=gba*?c61jY*dwSEdF}T)I$=dib+AU@*P

&LH12;Yi7wi*|h(UHLU-yBhS*hL~yp0}4Jfqx!#!%9hQIdv%7;>+0WPucD zG3}E6xyV3I*8wpZmBsz;whkIiC^7MCa!*GZB6$Wt_I6x#Y5xFmQ7ba2usYzP zy#SN4LNp%E_WQ$RT2R0HFn2{|ne@-$OgiDmlUnvK7!HosxiH8^UK+=KTH*~P(}_I* zf8tJScKEAW8bipb+n)KASq-=wS^lNQ<4y3`bKfy!r7>dd&rdwh6_Cg>6`=F6$wB`` z1lX6c)30YDs?Zhb+^k4$vCT51kU20`b$iPr(#=6j`C0Hi7vC(VFIqykNpZmK6>XW7 zi1EjYWOY-L$pva{O|d^|_RLkDq6i2A0yge=J#;7@9H^d%nCMeAjsNwSnibLd>}P=r zeZ8SHx@^4JiXQ-Q4gxoihqduT-+&0`hoW;|NjRk~hM)p37`VwW52xILZDhcrB<&VT zErafr1`LK|(TSs+x|=KK?WO=0jo}ZHil@%MKNbMm_zBWF>_#e6R3P;pfE=%sG+mV- zE*y!qFC0J8?$aTb+`#y;T@mZ{BQC-iJI8wrU+#TC^2QVCOv^!g=je}h9H}%#*%)&* zy1D^K=BZm@`Q1I=8~=?EB-e|=N>7)uC20C~kR?1O9E%G9SjUAd%SDSzq^u4mjW|jz zyR$bfO`wtC)u|K18HKJr$lp$YVS=k{DP*TPsZVPY)3dt~$&s)wn}@1De~}0PuE@A6 zuKg>ka_Sclb_=E)wo*~CLz@3k6lXC(ZlegWHV4m$E#49GES*kBoYK-)4jxK5i7b=< z5R^{0u+Hs65$Axh*ygYe|GVV?$4d*=+~fazt3RT{g}8J&vY{o}4yoV(cz)`Rq1-_u z;wnIQkW>o9)U+GBZmIz;w4$R4ozVpd7W+*DyyJ3_ZS2aez~4n>`O$zG$9^O=0W_XD za!_&v5qRB!^-F+1-Eb25d}4B)$*sJibOp`$Sb zWKiwa3X?tXdWG^l2rIua^?ZLhEVAuHM4PPp7de_94(p<_t1Py|6=02*DUDvuuw*u# zFiBbjzTCSoo4E-A?hu{Zd)KXJ=q%D%AhrCE8LULeq>Um2p{c67AC?uV3ec#&9QEC(}ZtC@Vm~0Ro!S6E>LV!TKpys^XnP1a6dN z+(Bv8l=Can8or7`xgKA7es^jcg5v`tx99l!#G-Rx$yB>i^eN{waC3H`mU0I=v5am& zNot1}%efiWIm-!FD1C|Imo=44cYvkQ>;*}-39|ZQ-d`w`9c2G)W?7LXvdk!eEHBy> z`Qt8x@{H0bZhK2ah5#njA9Aub)hEPV1iB&9HZTDILYyA*IYc1#;AvZmgqvR<^vo*0W$ADp!D_i*8DWzcVGLy09bUQ5+nr;t=rmL^A_+I%q{ZmOfZJn&65MjzJ#2M zyK)d0p`^GaG%=$@g}8_XjVFr-_S`{S^bnVxmN6d}9p^}&8bTn|`O8PosvyUZj0>+m z8%sJ5ua`4cVopOEOzI5P zc-#}7SR81Ekw=cKf%f$~qDxVZU4&KEl(>&V#ul)u&KOz?@9Wc`nw8s@e4mQLURu%H zd#>>ks0e)kZ28+ZXDW7RMBgf>-1<3L;K(T80Lha|4@9Mh9mB=!pZ$W8m zcZpjKia0H+Q@wum3Zl|?eg;_cMrETuu|$$$&fvKMeaZ<0Jc0LLQSP8nifD97(h(pg z<(m1?<0%l9GnFHA>M;)li#L8A-m%qx--Ja5xQ`i_{3Lzd>S&bJsYysVq#=;KctUfcHQaBIP2?_ zldc2!vHORb?#2Wvl-Xqe588X*^aa86URW3LCDD^NqmlbYGgkdRX4&ACf-K_)zFaXo zX@3Gn@^30_io#+`+ulJsL-Idh+PDlM(_|@)!fc)IQ+qvU2-o8(yGDH+_8~5*eUgW$ z2rU9zb_Q2dv4c*;k>3wmHfw%H1jvhlfIRE@D5s6!KtT+bS-CDahO$f?3Z_F}{mzk~ zi1S#K)S9wZpT2LyNa(aopIB6Z+y>`D(w9m(Y~W^%_Ke;gNP}fYl%yXa!|*@vQBMkh zzcMnY<79$a9Kcd2i$K!8xrTqws6m?|PF<+kQGZY5iroM*#=r3S?m~oeHDlG(#ry%= z5ai3burSIG-9Nt`see~#^JX-0`kFt4k}3$KlV+;2_XZ(G)rf-2AGrn~8?n7%i&OX8 zr{R^qz#gSLh%5B1^(DdGc;i2Stn7;H=nAyodSIT)IyNkocW@$TYw)Q*KJ~|^{`k}%pZeode|+kX3x06H4=(t@1wXjp2N(R{f*)M) z^FJ^6S)$WuOG|?3%;iuf%|T_-f8Zi%TqKQ)q;Zin)JNeWX z1fwe<8g0N0(b(t;qI{+WSt-F^hzOL%gp??P8w&ENuPrm31*~0oo6LKicV}{M-@83? z-nmVi&lKd)(VA$45S^E6C`5>~2M;BMN0ti$$8ks06y{_i=SadVKG{*7d!YuQ#ACsO z$aEROpge+bIhHdEdS!v6KNFN*Xe}!E)P=Nmk+W%X*~01 z_L<{XihxKJ7j7~>Tl6eFA6L`R{Cj=MA>A;&jifsCKFv_%Qbe95sY|J=F=I;4^r7L1 zL3lyfMzz;yVVmp?j+s>f74C z<+u9%>*DkvGMVL+bmo{=@`U4S(s0VB-m;$TCF;CRW-wuYo5zr(>uzJ`=hxKI@|AKt zqp>^n5lzw8#vjshszb zw|4AtWGxAbA{4TZgm3;N*snH@mDI^5kYyFjMq+NH*C}#Wzq+(;GBR;2&oddaAn=8$ z^vR{m^^>)cXnBiOj|kb4t2hV>W-6QzkW=vO3jqi~0zd*lg7{R12QtnDfCPX9fCPX9 z*)9Yi0U!Y&0U!Y&0aO>zr?4OhN*>6IAzc`RSS)Y@Bmg9Y>KssUz?B?;1b~EaK@V60 zu!MiY5|&7W0)dz=zX2ib*Wk}8=056Ug$!o!Wk%Ud-@%{fQ0`V61GQ;f7v%cChZCSt3+N_fx(%{-}wuzkhqfo diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithInfinityAndZeroInsetValue_0-inf-inf-inf@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithInfinityAndZeroInsetValue_0-inf-inf-inf@3x.png deleted file mode 100644 index 1202436035e64a071b15739e87853b93b683999e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18139 zcmeHP|4&m_6n~}W0s5*XZrJigsvCX@xB=|~4ui$jC^Fe*j1$?Q3do3#qKH%!;SECY z3*t2328C{mN*2H33}^(YD2ieLyD4t7wL)j{3y7jvWWdgSNO}LkemPCvm)`sCx#ygB z@426Q&S`gj9<@X?(PJV-QKE>YsudI^%p->j4J89nBcX5+q^(%8h&tKg^$5PWrY?<6 zqo^4nws96CQCy!oCudcY+~Lf1`Q*4Vk#*}Gh?*DoBtl_Q`fYDxf#xX1zwl#tP-SVHx=&wW-7ElGq&bJ$Li^<}ne@8ICHX!2d)lgHRc2$dYx#;DHO z8Xg_>6fyy+-oh}KQ+@6|4KajHlC;1%^vR{#L$B8X`RO9NY{$liU9%WcSI8=|oAm51 zj+Gnq4)Kd^iTa(vVN$i_2EF;8xRz%RwWKH714zzK*4gDc(yWM{c_aRv<%+dX(-LIK z?LGc_bDVh(P&v1c)$V<=Ait*99Xc?i0m-oT!eA3e#7QuL>$TFeH@vC$QU1^{BR3do z7;8*+RsFO~PLMC9P-i^mKQP}v&|okz)|A}tbSt4%0rGCwJdUcH3o`afg>G-;Kd0aM z5jxfCq3YR&<`dQAxoTEx>2~hFXg(yMd(;N!8Mchnl=p1VX0mYGwJERUYZHNOiTyA% zs?9Q%)$a+WC98w>9|^1ui2@!h6~MH)&t$rgkpvI!)W~KIhy9Z85d?zY{|JP=Ff`Dv z2MQtW$_3{0MYir*Z^F_2oGFWHEbg476>{-|ib<7aDTJYP#xAREi8(h(bBVmwMA`JG z$DR9PIelprK(NYnb}9G96}0i+8QJtKP7{7aOSa;yHzs>R4(sRHRGdA(zO0kzT=ET& zv>x8n(VE%-Bo}xT%qjXpaVw87)tob>;Wu-0*0v9cEFaSyfhYSU=Fy?h3d*&A6>Q!T zPl&io5OcliQb0+UD?R%MyUi3$3hCeV%)avWXlB;(+LO32cjlzjFE3Z6`Pd@T4 zXd4KRp8TavMoEmH*V7L%M415Y~8D>v&P-y6a{n%laRc3-oAtUGD(+6bv&$O)tW#DkD#9etbbuu z<0hhzak6!6!R>3tWquAGfevpVjx+jGu(;~Y>NUxY{MM258O2riYuEW@%u9OaDxXNd z6Jt^n&QO_r1*=h+I5Nqc!D-GjMGV?Zw3!6x;R1xK`RHpz5oaRKL; z(^wjZ@^?d?Ccpjb4E_o(d7E0}$WvJ^oO)3jn_=Q7w5Y{O2LR$8RER#cuh*K=N!pP^ z$Z$%4OrfS|363e47C8GL4-QQNB(Mb%+1} diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithInfinityAndZeroInsetValue_inf-0-0-0@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithInfinityAndZeroInsetValue_inf-0-0-0@3x.png deleted file mode 100644 index 38a85d9317f935489a6e883dc758f30f61ffc118..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17062 zcmeAS@N?(olHy`uVBq!ia0y~yU~U0n4mP03Prv`xK#H+A$lZxy-8q?;Kn`btM`SSr zgQ5ipGrCSQOaKbXWV-l=0BI&51_H)IKtcmTgV>7vw?4~nW?)db?djqeQo;D4{q{jl`Mf39OVxi-gf4 z0o*njZ6yF(U!z6BXpsPEgpaloMq3G^tpr%Fb+nZ*+DaI0CBTMfMq3G^t%T850&FmJ zwBs<^ae$+-5=L7Iqpbw^)IGh27ugvY{{NSq zGMfds+`$I4%;D`#!!Bk=0hWVRzy8#;uBmfjJAQCiu%zGOz2EKro59@)jov-fh-L;RScM24PFs+faLD}d>vh)1D-w8^ zIAG-jr2Vk0k@G&!`rYr4mq{3KD4;rP7Mog)@t$|PP@JXE0Ja8Bj5-P!6r&*p9Lyd~ zQxXZIxer*rj1~!_MZ#z`1FMxsi-gf40g@I*TM47B1aP}~v`82&5=M&zSdVnH;{Z$x zqea4KkuX{$j1~zEg6fvEI#`F3u0#Fq&#Vhn4h&#cw!2~<> z1ZvB^{`;PXCb7Mt`2xCCi@06p*NSh{M^k#0Ri*{aQ91cudG`uqMannWHW`$A;b zgPh?a-eLD!FDV{P=_+mu4qb#l!46i~6d1S)ThJrn1=Gd!@b~ra(PF0nm(R)t ze{VuHBOvyGV+K5~p$@*ty6F76d;jm{qDnjv!{M{{O5ajZl`hzYBYI=^{@;5WHQo>C eV)5BCCVO?^BIASwzMP|gZjEXc?wqV!*<--L>rh z*1U3NU!vyT@rwEpH$`)TT11j+BF&N7qE4h`_`pQb;_)C2anA5vDSWstT;6?|>`YU- zcprRZc@yxJRCVW8kODXztKL^?y;VEsNm5?L=cKq2g1}l7+43Dz4B5knoS(}NtBMM4 zj}=j%6pR$jflcAZ0-ipA1PL7hJn^IikN}V%aT8z(n0)~x03^sH99ROd1Yik@*9t5F zSOTyFWqAfz02SJ3rkLi?|KU~PGApZVU43$c%eH&aLVtboAiHYjt)Y{lmzzo^XB7-G z*@Jmy9jTMD3S3$(rBfz5X{qc=p%6@K>+`Q8vke%HUcmsF8{F{B2r+ja50EJkyxyb^ zjnul9US7GTX`pcpp-8~wmc*z~5i7&H z3~_ec|5Yq`-;zr2ZH}mTNHaEXSLzv3hifzwEO1_``LyNS(9oCykw}}&@p^-;+oVdu zoz56}{q^wvhRwtD9y3uP>pPVWtIQ8Canb1S_;&#Ec!4$g{MNW6hG$a+c5_>c<9y8E z&nGH+u)L{t$jvWKHh&3?#zXE+Lco-w&-Ie=d()AC>0Fg7Yz)ue_mrq;!1AWn;cJO(bU!VX0 diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithInfinityAndZeroInsetValue_inf-0-inf-0@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithInfinityAndZeroInsetValue_inf-0-inf-0@3x.png deleted file mode 100644 index 54b833999480117e78a0cc4d74758fd884ed498f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17051 zcmeAS@N?(olHy`uVBq!ia0y~yU~U0n4mP03Prv`xK#H+A$lZxy-8q?;Kn`btM`SSr zgQ5ipGrCSQOaKbXWV-l=0BI&51_H)IKtcmTgV>5L)_>bq18D(I7srqa#y2+&yOEj20hSgLf67M;u@RGbh9-{LFCQfFcHzuBlUOfvSKhb|_`sFA#+;Skm}n^Xl*W%cD^x zcCgB{pj#yntMKd1?vC0>RHZBQ9w=-*qVwzS{lAxsD)B(90K3oLD}75vRjRP-06zo6|Nmtv zl7S2i3V%RrBi`OP$a}y*;IKh|-R$KrWR$x21iI&^RNKJ=8R}vWy$Lp3yfMOh&rYnC zZ`{iYizK*@xfh~Gl#6(W+-+}EuLG6uz+oiI;5Tx2b)7VH$p~~=h%K}5Uh&xCvy$+V zK_cOSxq*NK5`VN)G1{pZ?Nq=TlB1o9(M|;{EsS<5MmrUwoeFqUVYE|0MW=5--(P{>~9t=W^773$8!f25&S|p4X38OpO4vcQI8{Loy9@Zb-x(VD5 zJG#l$;J|2+FuF$>vR!+$NEj^=z;nH$MZyp&66{dfC}b|F86wdKdFn=jRGZ9HGAps5NPXHLXMRXf+hSRpTY@Ci z2aW#v2SI~iCiKN=_WVNyr70N-In#HER(@1_D8LXsYwgh$smBr0O$m+)-p83O00{t|LL7lGgJL&80ziU5;eby8^YoB#fCPX9 zfCMpX1(pCTL9hi#9H8prDR%)R03-k;h!tB%93XLk#KF4}0_8<0FG6`y$RB|v080Rt zAV!9N%@Q6x$=}PXyQb_3*pBz2oR!p>@|N=SUHBe;j)Ij)yB7}>js2jW`+nf}&`hFr zKzUkpUnINb0cm9wV@E&NKCB8o;oFzL7t6^MHoF$z&X=h<+5Vn7hsHR(a80m%j{}$( zxs7fplwpD~I;q??IA@PtJbC8vK)HADcr}RxD3Ru^65;pIy6$#+4mRKDDPF0PWLYr{ zbINnPvZ}&R(>A%Q@oK1VaPyiXG)K$EN>{M?#|hAe;vG8bQe4NZBMws&uQX%&MHA{3x90lh9Mk={ zjzB16r=Tf@1)D-{0p5oI1Rwz*L5L#&2>=Nm1`Ch?kN}V%@@8NOz!C&ofW!fX2Ve=n z5`ZO$Hw&1d*DQuCpg{<$nM_oL{d1 diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithInfinityAndZeroInsetValue_inf-inf-0-0@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithInfinityAndZeroInsetValue_inf-inf-0-0@3x.png deleted file mode 100644 index 2c9f2facff92aea74a96cd7f1334293056955fee..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17074 zcmeHPTSyd97(TPJO>559YJ}^SxKc*-;+QK5674Q)Dw&mZAxfK!N)uEtQ_$F5cN2{s zBSeXA5K*)h(ar0)non8U&8WO=ff%N(Bwp~cot<%JN65!|`WNQR?3^=mKF*%`{_j8k zKU=*wJz2d%w*n!gPEE07AVfO-n~K6`rqg|ict;dvB%6`z^|~MUOHg6T;Ua{h68syH zbS0L>C)ed#_Uy-d1>W$7aN}Z=u=gKFt@`{s@-agCFR2#O{!-%STT=*U)U-V`9vf`h zymB~1@#tL1wP_ncX<4Zl3a=Sz8mi5EjYyi|7K#?T9VukrX{O7-cVcveYocmM>;YK&sv!W|9jw5e02y~U>`psdYq zLIi+jOMRD$TWf=U3D z04hOTo&l8rDgji2xEKnK12_)CTmY2-Dgjgis07h6fJy+BAkGC)37`@{B}k$B|Gm7p z93h`C;&Po5r#qzh(;P-Vb>~K#G|JYk=eJwU2gi-nx8^5ll`HQ~p6`FNqhN7X!8n~Z zo^`e}eoy)`ZyU7PH*G8k%}B$jknWVKfEXh!+{h43Py@%U{2wzBzXETfdC~i9FQkA zNuka+NH>j+Kre?EzW3jwR=L>&xgGz0d-?mD}sBU>Ov-4wO`}$`B zG3iFu-!{`B4{+xw@pH*i|A$0tb z&mF?S=;klvISUHcoCs75d|V2{uh62h>aqF0YkWN4UkofGsT-ytUAxp19?E?rb=)u; z+@tCr*wPWG;O;Mlp)Y!HBJ}%Q(+=t90XJ R6#pv)La9mV7MGc=_yfsfWn=&V diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithInfinityAndZeroInsetValue_inf-inf-0-inf@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithInfinityAndZeroInsetValue_inf-inf-0-inf@3x.png deleted file mode 100644 index 3fd9a4e1bbf056977cf6860c6f4fcabfeb73c172..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17201 zcmeHPeN0nV6n~{yL0T=4No!%22C=~}pK;ldWnLvlgN8F%WgMe8HWx&QV z6*Dm)Uv61gHcXK~qT7VF;DE)^fq)bBD7$4d(R$yc2zEWi4@9nSC7E^V^f;XD;D8^a3xd7YGr9KM_M>@c8$}5p#zaOOFJSz7H^Nyf z;dWn_q)v3av~|kauJufQqotU^;>p&6Nq+TY$K;jMdWy;R)2;>@m5Q=k7iaqo1p1BD zj^z#4uP@AE*gr1=SCS!ZX>R#&a{hV&JbUh1y>#w4rfVlZC4YqfTnU+sE3wJ8))>f% z{Uf7bBrkJKQCYDnf?}XjXekyC+Z1#Q?0pCcG&&-9!k~nZfRI3Q6J!a%z7P@+609T~ zSpu>IWC^ynR%8jt5|Aa>+%w1$kR>2XusK8V#Q|R&tZe~V0g|9QAk7-5w<_A&qX_ zac9xNs=-(1;Ws_Xwsl_Xpni~9(dm|~=wCkp!KhJ5C>5P<3mybk&TW|TP(s<+#zm`F zZAj9!VakJpox?vR#xWf=|DN(7bP%ptk5C7a!G)j?fF>ZCz2Fqm}l}-Q$SEyV-v7ORDo{TNk7TvS@$qb=JPpeScPY8{Vv7 zuwYmLe#V z7*z>Iovrn~k#UD)d?>LS6<_aM4A5#z7*3uhC%tl)2~^(7?0E8NgQE{9qSfx zeSTo}r*rV=(yxk@ALqUkLaL5~o9UmK`F4h6o8_c`sM+}$|B5HM&uj3ATFs`>Ws+}d zNA#_!o}qX#(V(}uY#>?gMq4UHRH^F-3RZ{?kd#o+&6GWslBEOPPTY}{B>PmSob`w8 z8ZJP}1<}~;*j4)uh{B%0KPWH5jIUFCUmdZ;02Ip;Q`Tzg` diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithInfinityAndZeroInsetValue_inf-inf-inf-0@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithInfinityAndZeroInsetValue_inf-inf-inf-0@3x.png deleted file mode 100644 index f68b2bd9fe5f045a19a456f91600e7421cdaed74..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17906 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 diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithVariableSize_10-10-10-10@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithVariableSize_10-10-10-10@3x.png deleted file mode 100644 index 3004b336f288cd01168bd26a6be2766b7afeb00b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 589 zcmeAS@N?(olHy`uVBq!ia0vp^Q6S901|%(3I5Gh##^NA%Cx&(BWL^R}oCO|{#S9FJ z79h;%I?XTvC@7QZ;vWK}L8?JO7l<{WG?2|Gv^@63Rv`bLr;B4q1>>6=j$8*6cw7Se z-<^%#_0CBmiKTMNJ0G$6^9|q5D7L%zmxt}dZ^ina#=Kb>3mV@^zFhYr#bmK$t}M?o zhZ2?xlVaGVG9+~uH){&WGMY%{z1p$UY`@8o3Cu{{GH|uvCc8MKE;!8Jy3r8m z@v>JMQLGNkwPAUnApN~wc>~uHWrkd~eas~cQWsn=G~AQ;!rLHf8FP_6-4Ezj22WQ% Jmvv4FO#tCS>Bs;8 diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithVariableSize_10-10-10-inf@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithVariableSize_10-10-10-inf@3x.png deleted file mode 100644 index a645e3dbd4557064833fc1f7de40f0dbab15a0fb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2062 zcmeAS@N?(olHy`uVBq!ia0y~yU~U1jqd3@rek?eR;ebMy#97Z;Yga#<_kBy0m z14)s=fdk7LIrdA&mEV7s^i1#ho#r&A{)lU$TDiwkPfR$P7}6& z&ior+tSgP2bZX8zMA@$>=6jY4lCsB;I^mch8TIWCn|ONO&NqgL z#8bd_sfvSrp=!=e8lBU) zMedMe24^ d8fJ(*OU@-p28dfq{8HC@;UguE=*J0GN~I_nPNBR;+AvUwt(2^RwnB zmGicLJb(MA>AtIH`V6bLmm`JQKi(x<7o4-4aq8pkTN`)&|MB*C9U_RX0VNsO7aqTk z>1DBp3ST&|cv(rNMGi}RMF9g^8B2V17YI~giLY!yKBs;x@uhpn@r59k_;R)2u*DKz zTY;&>9ZP)C)bSmz6+B4EW3)7cX06fU9uyE*tHuY+tKS(o{xsFw3Czzopr E0KT7hVE_OC diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithVariableSize_10-10-inf-10@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithVariableSize_10-10-inf-10@3x.png deleted file mode 100644 index 8a01a112f592ecb3f7a642757b39ae95be0e6d5a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3019 zcmeAS@N?(olHy`uVBq!ia0vp^Q49>sEgWn>mSTz80U*U#9OUlAuz= zF2Hi}-W-7%PTv1i|>*}ttN=I^gs%y!B=r2SRJw#|QBHhw(DyI3-|rgq=X z#PpwRizWZ&r2p(pdfY4RX1wdiubSe+=RWbe8UMO@?vwD*W76h5X(b=O{(ROp_o+0{ z>dkYXs(1C8=SiG>@#yvEv%J=)&4J8x>(l-s()l1uk6wR1Te@soK9G67Y}$McvwJ%# z&%ThZ|FQoI?}F{&$KyABJT`yo#h!nE>pAZjyj}}Z2y|%t}V?788z*iDpjKDx!1@zjii*i$)xI)|;$`0{fV3fMxe4&A@>UvXx$zsXe zQl6y@84Jp<0>kBOM!y$0lB^%Hy(>$ zf(zyrFqbs2LEN@g0W%602Vspulf`TM7K$(c9l9$K=z_O_noAr?Su)h`Fvu=ov}NH1 zx<;1+9#%*B+Pr;f>n}VI@8FX8w>=-Q0%;~88I&HJ|IiLA|V1?K1Agi@9*;`E(J&iL8l%~15SJSJ8s-`}+R0wu2WoA5y85}Sb4q9e01iy@u>b%7 diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithVariableSize_10-10-inf-inf@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithVariableSize_10-10-inf-inf@3x.png deleted file mode 100644 index 4367dcf7de947a28a9ee8076db7e4cee4857350c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17135 zcmeI4Ur19?9LLYy#=Miwt_iWF*d&W0jEN#j3Y$$-N(&LB@XsJ@hC#wIM^-ppNe@vk zX&Ty}*I=3W(x2sA4?&r(M5ck@UTm3#QKE0b*zJ)GabaQgG!9$|ekX8S7^?tLfAZic~t*7z|L2K#Yl+nsjAyf7dY zj8)I;nLYaMJWb~MN&8%@l|576!R*m1&g9-$z8z@w55%s{DLaX5T+1`KIm={j(hjDFATrjP`<~L0JV%?%#ol*bvDKA}|zOyUO(%U8%#p8uZH zVG)e6fW5ett2w+Dm(yV)o3lvJDcq@uN}(w{eG))`1Rw!Oh>pq_kf|1c1Rw!O01}v0 z2#^3I00}?>kN~d>{8Q8y2u~i(EP;EG{sIn;Sfv(701{~E5J-@sL_h-70+0YC011(7 j0?ZPmBpV>%FCZZyePlZG!)1Mn_>UCjC6#7Zv8D4Dc3mCP diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithVariableSize_10-inf-10-10@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithVariableSize_10-inf-10-10@3x.png deleted file mode 100644 index 558fd8476866d10a6d4d4ba3f1141704ddf8dc0b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2088 zcmeAS@N?(olHy`uVBq!ia0y~yU~U1jqd3@r@>vz9HGT*>}Ljh_m)Ph-T zYBk1t-t97myTRbV0fh!6`+*8Gq-K0L`(fAXbI6WuW?&k1)If*SKi)UR&!1oWeSa-` z^}2W~yo|J+sg z?6v4_#iI1b<<|OKw zwyimi;)?r?)8YhQ_|1F%^XFGKBm;o?<@0HG`}n=J`*z*f`|klFHv?s6F)}awFY&8i z6Df3fWK0tjY^3UPjUQI$oJPvC755t&FF0gKqlB9~uLMVb+xFVZ`rnVv?zM!Q12($x zf*DG1^hp^A$noyqHuHn+wp1iH?#VykkfE@JHwiiN7PIlRxF5c~Z_obPkI(MSfd^~C zS)9&@zwPrw?zRz9q}(%4P%sg=#b$_HegNb8(Bg-=@%QfUt0>M#lo}h-a5`gsu3Alh zt|Z)hz@)QxmH#4%C@w&`7Yq0CZA>_1`%bXeipr!*6|Dd$&%Pg2?+@rS( zIX)b2JKPetkWWJLfJ8#VWrvoVJd3;akOIu$g4u*`tmoQiz(WP(iW?>ZiDrjiEaDz@ gCMX1kc4!`uKlRbTG3f9LYfw$@>FVdQ&MBb@0F5JsE&u=k diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithVariableSize_10-inf-10-inf@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithVariableSize_10-inf-10-inf@3x.png deleted file mode 100644 index 10f466575a66a5e55cef37aa4706a43b5dcb662e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2196 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 KTGL;lKmI3Te*YK% diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithVariableSize_10-inf-inf-inf@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithVariableSize_10-inf-inf-inf@3x.png deleted file mode 100644 index 88d16405d2b71a4dd48f0824b4dfe3017e97e34b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17997 zcmeHPZA@EL7{2Y@IzDcN%7X2HSp^rCG}?v+gqhhwSz!*`<`PGQt&G7~aD|K_j0kea zhoEj_(dc9>DAWB?ie{TKsN7W?EJGMfMNyz=L~yQF7t>a=)^kel2gbkpL*FL%-uB#k z&OLe0^FHT&pL5c-?YTy2*t#%+Af(w@hMfdKHsK>gf=ax({!Qp2s@!QzCwj(Wm(Y*U zimbd!g1GNte26k%)tFFW>_NlhyU)C|F%dJibq*Zn+U>q|M% zAd<*U%O~0|5sO2F&oRt7y2kVA^KR$t8U8tuL@ZhbkNv+5@?=W;T#>K8Hs!g&uLB?o zSrr*TSpE#7>1y=a{_ajgM0$(W{N>!ZnxtZjmBu^!2JflG_@k>8F8#=4zsj4c(lAU1 z{f_kF)X5}-Sa*`6(N$mmW3Fu@La!^1l>NTx&8jb6N7naritcUdD!caXMFd91CLJQ@ z{-AAEcX0!~n%o?cy0^j{{{yNMN_vMPeoHDW#xVDsLzM>VZk(R`B!;BExvFz&uS5@D zMXvGmI+y-KuhTixkKb#JX>GL{Kii&xy64!9nmci8e9(tqR3#nyuE71vz?lzi>$!wZj&%`MafoOHd$(b)d7vD1^%iEVvI z*=<>yqb)=Y_7pQ~<}b`%t2^=#?#LsOZ#84L<+Jvu@N?tHxSsr!Sqtv4oF6C{j(=)6 zI7(ej=E)D9Eh@o=57I0eeVt(`v7^+^@i7{saLN1X$t}a9!ZPYS-8#8LJJBSp98K*n zeCyb8>;PPY@={Xv_Sw?zP?q3PgOo}>V$X_+OA?l;uS@RVYMd}c2`lebw>O_mPAd_X znck2ZUOCDNP50Q^2 zNA5^_VMB*t9%7iIwCbhv6B_Jse5(Rnv#lbJ21By*G#HWv3m}qr9B^%pZGa&NyK-lF33J`YL*b;h}ZdcJCE#qK7_Uv@X?ZZJ*dEmH;6+(eCDAP;VL;qu-bGU_A6 zp6VIlnzt!ZCm0&k6|Hoer=(`4YQ?rIJ+X3k7IX?MwTx206xv?`-bbl{5`Yqb64(VP zpag^kpah@sEgWn>mSTz80U*U#9OUlAu#p;5?>kL`hpaoV;CbD~3cr$?I?FPeH7kjo@O$%Z$xv>3J+r^$VV0k-%>8juY z-yMur4$M`YQWqTVM+x+#nJix0w^W3I_siN{i9l1|25K&GC}qhI&THVi&=A+e2GlRc zvRLwL#_D8ERtM(V)p-(UGu(j1vSxrReAX1E#OdKKZt2sCoAIt6ziNVWY90fNs=95PYaa1hpDqWgIC}m0 z?4-xi<~?a&HqU)3oPQ&7U-QKty?u7~MWpZV02WyD-|Eb-IDGDtY)@Lr$FDz^-S}~g zcd_K(ob;bZq|2tgPxw;0xLb7p&u7_g|I;#_zUSNW>VrM^-cR}Oz5djF?tK*?yUMw= z1ze8)31i^h(s%8mBI_z;hszheFEp_Iy2dY!S@gZ;z*6+R_=Z3IG5A diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithVariableSize_inf-10-10-inf@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithVariableSize_inf-10-10-inf@3x.png deleted file mode 100644 index 98a3f5faabe067957a89db6e3a0f6ca51aa7dfad..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17135 zcmeAS@N?(olHy`uVBq!ia0y~yU~U0n4mP03Prv`xK#H+A$lZxy-8q?;Kn`btM`SSr zgQ5ipGrCSQOaKbXWV-l=0BI&51_H)IKtcmTgV>7vw?4~nW?)db?djqeQo;D4{q{jl`Mf39OVxi-gf4 z0o*njZ6yF(U!z6BXpsPEgpaloMq3G^tpr%Fb+nZ*+DaI0CBTMfMq3G^t%T850&FmJ zwBs<^ae$+-5=L7Iqpbw^)IGh27ugvY{{NSq zGMfds+@Te;%;D|zgS|`+JS+$K=AN;fYsR7M%lXkPXS)2m&p&Hw_oA*B*pRMp@%y6e zb(YAh2>wWOun53%H>B40W#-(EzCuBPLjmq-uxc}2l|L9O6cif3V{LHahRK8v7|SM_ z7?@ynD_CK|Wrsr;%O*IOI7S^c8dAW)>(MkNkuaM3fF;vtkpL_%M~j5fA^}`$jur`{ zMFON5HCiN$773$80=VlkS|p4X39xSCXvYDV7DihMqea4KkuX{$AdTIP773$8!f25& zS|p4X38))2M~4?jhZn(}$kC1i(H)0%0$=w2jQJa1tSgN&r#P!|UEPJVmN&k?`adiC zC-P3`2iJK@zBbFWOnZ20-p)6Mh+WSgfZ_stPTm!%=VQLXN@rkvRIu%;;$UB>x@S|m zUNzEoYa8ZR+m_}FLUA{Zr`tm6GqA3CjqBtNIc9LKe>3y69Fn8XJB0H;RM^rI{_RX^ zKRBKtk)6I^b$fw8)FJKaXPb^AHh~{7zHrsqf8A?F!4b0#VbXi^FNF_ ze^`dTO-m|L#R!b@(Rps*=<4W-0N|cNY|9jWFc&9WRVg*r_W+$p;pyt_5> B9OwW5 diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithVariableSize_inf-10-inf-10@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithVariableSize_inf-10-inf-10@3x.png deleted file mode 100644 index 232924d3ddf12311a679a94efe6b8929a679ea99..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3015 zcmeAS@N?(olHy`uVBq!ia0vp^Q49>sEgWn>mSTz80U*U#9OUlAu0(#dmet87tP33PN0|fJi)ur-Kn86Qzt_N*vA{h8D6vZc(=hj? zqlS%!*=W*m7|l-fEj2#eUr_(=&wTsT{dJFdGhF}seZ0S7^PjdwqHABQui5)s_SpIT zQOEvC=da;g{kVAU)A*Xj=RQeyg_XSg`gwNHWAl3&Q5WaG*7^TPx^&w8fGvx>*U!H{ zMQZ;?w~LDx{RbA=|Npbt^vwYl&r3nY^V=H-vn0X=TmoyW{_pJh&eZ7?tlZ^%LM`RV zlY-rM>*UM7|2%eIe*XJEUyuEN{XhQm6e`yV_%g4_P*%&_*WA8Y5H-2ZX%uX#VpMfS#h z5x)B8>HMEj7waXTcK$cJ5a#~ee}(^*-&fCvY*{4wSG(TmPu8Ak|7TuJERB#2a|e~i z4b%R_F-dKa&2?u772z3WC7iq_FV^0N)&*Xmy5QQbK%n-wYn5j(tyXr}{XqHxqtpu_ zsf-KJ;w`{1%m{bSToC(#_XPtl z#A(p_XECV$$zLlCs@3GCHfe6KV%oyJk5P6(qu#fQkRg((~w(D_#^sno?B+|gPcWWM~&Z-XKT6W+S#|6C~Y$XkByFgXrHP(fo z%J6F7EGD3yYrP;(_j?@_iI8Qy#d^Pi?}Eeh3%~$?)p^K)7N|KIXrqBPn$iYG_Wax4 a{f~V{sDY!n@bz?1OWV`c&t;ucLK6VKC<1E$ diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithVariableSize_inf-10-inf-inf@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithVariableSize_inf-10-inf-inf@3x.png deleted file mode 100644 index 651468da4d70cc627bbdd565af68999d1fc5083a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17151 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 diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithVariableSize_inf-inf-inf-10@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithVariableSize_inf-inf-inf-10@3x.png deleted file mode 100644 index 4d863686b85f90581a179ad3263e990ffbf84ae7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18021 zcmeHPZ%kWN6n}5UN2N5aS+cflDRf!P5``59$YeEbR|FzsZZ7H;kakNt{&cQMSwNxx zq(yWZ{o>LM76ja~EpeS0Dqt*c9pVSeC~l@>qn3Vfsd1Z)%|;QV-q)^umk)k5F*!}% zpT6|nbMCq4{?6~5d(-z{sjK4W>~({gE_bqda_iPs6ZFew697{T)MvL zH}vI6WAymWT?=b8s{I}0 zy*X9Oq*9o5^__8xXX;3>lp}E|UcMulYU`Ydt#tWpBqi2nP7#SK@?GR~>ve*YE2kfy z5)`$L%YH?7${V!fSWlp#9e-DxCCt2%{Pk|mdXMDI_Mn7qU#k@=)6J$@EaBJ2^&P?E zM>0BSZFUtwV)Aq4{t|h(FMK?323M9Mvp^}Zlo))9nL050kQD$D06dd%1i}nJLW-LJ zBmg7;B&2yWumoTUNnd~z3xx+@3BVG7C8Wzg00{sIDPI7V04xDmLMk!A^q~v%Gb|_rhrC!h?#3 z+8G5exH3JEgzgl6e?#)ZF=@_Ly%%5Oe}c0?%?p2N4Q#Mn?W(d?v(3F#rj?Bd4|4HU z{DKx*E#_NepL)L?8!BcO^rIh-*{&-vr-2UBd%>F22yUN|4^p-3c@XGJ3fvE>4@apL~m-iwp333sUq zgB1e@oCcLhHu1#|{hN(vcFx3N?hw{A>T8E(DKg-;EO(U}0#+kyJ47C*ZP|l~!;ysR zxr}~tn%>KiI;yU@&8MP^@q@TJ%hXP;f@@x@`!IU=anItzU;lP*vzR7!WQ;(cCIxDN zy0IGP@Ad}@(jk>GXn70W9c_w# zwQc>XwDCv0PoEtvxKA$1^lQvs#@D!}<>Qexj(n8UEEp9OXH3Kl_2uRQuc2qQQiKa@ z+F0F5n|oP*MDpyrIZx@ge^@k*Z)8#4QQqb}*yUrL2HhF*dgXn(wpnM!Tu8Os)K5}l z{vlk7R(nI~n9ChLQG{F3U-ro(+p>^#Sw>zTwb`c^H?--nPTIe=k7Uok=fb6kZ{(hQ=_#F}MS)#C9t}*uf$P zgdJ>}Km^B_29P0angFlF_%Bd&Y?=T?#}XFEcCcvzi6fifLJp1>8larPS_8@%YyuDE z42*I?kqygCXeei3)_`&blrsP;0V`o`2bRg0l0W3&kb}eGEmnFEL%kBS2GlE|UMc^- btnFBv_&;ySSMO0U{{vG~S*N+A*1r1>dPde= diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithVariableSize_inf-inf-inf-inf@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASInsetLayoutSpecSnapshotTests/testInsetsWithVariableSize_inf-inf-inf-inf@3x.png deleted file mode 100644 index f517f65d5c7d5824e19505efe73e6c3f564ef4c2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18175 zcmeGkTTl~MbmL--l1yVCm;}V26*~jg1S*M*N~ADoq2OzHD27y!m=O^P*5E|VY8*wY zrgnq@5wRVdsSln`YpKzdDi1A$+Oa|v60Ak7h;cv*BGP*ogX?EM`gbz3ce5vV&z?Q^ zyziOhE{=&5Opr_<2tu%EVfa#lAT9XdaS>!7W>|$z9K+JcFruv4=K;DHpSdv6KoEXP zd~hQ2kN02F`aiD!*5=IO!7*B9BjHd*X044!Uf;-TJ zC;_5`5m|u50TKsD97a3?Bo0jF0Zamz1TYC;65PQeBo2@`xMcwn2S^+saTwj8f$}1h z7ooh!1d9+QK$P(RMhWpjEkla!@rB2$`~BbC7^e^OU!+a$-c~C9c;ALGZ+hsYM)NM~ zy?~rAyo$wI=MnDnuBO|b8F<&9iWOA|v!0HRFKc{{SIBK@)7fWD8Lm zf))4{CAy_v-)U>vfiNiZDGyb=%+|LW(dH{i;7!rh<`ytcXl_c0ZrfdjOpdLPPaAqw z`?SHnbQ7ZID?#?%-M#4=U*=tP`~=>doVr{`W-XdISJJT9clT=lG<;EX&AiK%WILa{ z1!Jj~TSfJ`$9H)l`sj6tjPj=a3PTERl;|f3VtDv-K}!QcO!vZF7LQt^GQ5|(`^kb2 zSE=$lEB!4cv7sl0scEfu9@J2(AKNoFZ=cO{Qz+ZiJ&plGR`9X*CZ>_$g*T5UWnQ5u z!>KCY`DDt;m&*zmb{WYzL;1up$E+%bMH-&i^%#+f$T4uI-Zpe*|F$2^J9mIH%W^Zv ztEaXaKcP8D_*VDnaa}n%8a(q`^y9(Ll)qXq#uB-;YoAFF&7g}9aUv!K4EDA4r<$n% z?}o#nMfNTuvj!4U!<(Zo>X*b|@rWcR{w3e*Ux=yHiCtmF-+Qx?izgvUGAENyWM#dw zxt?~sKE`JAq}qEmPfmDaDpA7-W|r2Ojj)O5w^!KhGLmn)roQlW=TOpprn^M5hW7M} zDzCabSaF#kFQ!Q^hO}xTaYsovdeFIlqT9dIT}4->I<@6x^xC7FuvB*FXwS~UKeA5E z#1g(<>g#$&J~PcrMhi0*6FxllUPuK;n5hO&_8H z_g7xo7{oX&_h6&;+^E0)X#k#&DaS)XkhN6)y)uRk)0QZNmCqAa=&vx#@oI?TR((|G zRo}>l@%y+_x84bs(5 zE6-lv`x+yMo5xSpe>wBO*KC;Rz99Vc{JgjojGnzB6qpIjWK;+w)2)wKXF$zI%@bw^ z*i5jQ*foL!0&mU)4iFl#?IXmQ5N9&c0|f1C`v@5jq?1f`1-UufK0`>0ohbdnt|!L|kL0l|hE>`uN85+I#q+eb(zM;#~L^oJ50l;E(t kfQ}A#XUu;s!MVn@T5i05Xqx>X{)d`H5i#LqVcH%40i_@% diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASOverlayLayoutSpecSnapshotTests/testOverlay@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASOverlayLayoutSpecSnapshotTests/testOverlay@3x.png deleted file mode 100644 index e9bb3f4098d0f6aeb6457d2fe2eebc3083b3f26f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21094 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 diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASRatioLayoutSpecSnapshotTests/testRatioLayout_SevenTimesRatio@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASRatioLayoutSpecSnapshotTests/testRatioLayout_SevenTimesRatio@3x.png deleted file mode 100644 index 5fd4b9237df9f4ec3afee27418e7d2cc642c8558..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 651 zcmeAS@N?(olHy`uVBq!ia0vp^S_}+~Ivi|3*4DR*pMVr&age(c!@6@aFM%A+0*}aI z1_nh75N33pW|#mJl*x4Q4*}9lKnw!YfLH@c1KEtm1xQiKeEe}9~c7vpDfoo1`LY7prCj= bQUl_Yqp<&`sL&o@Krnc^`njxgN@xNA+|mug diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASRatioLayoutSpecSnapshotTests/testRatioLayout_TenTimesRatioWithItemTooBig@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASRatioLayoutSpecSnapshotTests/testRatioLayout_TenTimesRatioWithItemTooBig@3x.png deleted file mode 100644 index 0121889335374c5078d9b89a0c1f6f8aa8e7038b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 513 zcmeAS@N?(olHy`uVBq!ia0vp^atsWNIvi|3)|Ic!8-NsJage(c!@6@aFM%A+0*}aI z1_nh75N33pW|#mJl*x4Q4*}9lKnw!YfLH@cgV^sT&M)~4q<49`IEGX(zPV(`%V5C6 zvhjoZ+;^-G_-t7Zc%D1|W^whDyP9WMB3{T9CaN89`fHH|B-dIEJb8cpFQDW9|9|;J j=rWM81LTXhL(mWL8+lLfSX8M7^aF#ZtDnm{r-UW|(Z{`& diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testAlignCenterWithFlexedMainDimension@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testAlignCenterWithFlexedMainDimension@3x.png deleted file mode 100644 index 4be0521204ad68c1265713a0ea2f22a0b33f14f2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5170 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 b>;>d=l_+ZXM;#a0e|iqKj?|I^^u)ga{$OUm diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testAlignCenterWithIndefiniteCrossDimension@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testAlignCenterWithIndefiniteCrossDimension@3x.png deleted file mode 100644 index 042dfd0498c7f47b1f69842a1aea9fe8e007ca5a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4521 zcmeHKi&GOv9KOq4uXoJp#As|pXpq z5=u=_Qmu}nEliO#1}P{$@IX^54mMg9MTTY^93S9wU^0VZx)J_}PMe$g&ED;P` zm_WdB_Gk)phJ7BpA_cT85P`=IV&-@Y-U$>kUFwA(+@pzArj){i-R*^_l0@3OM>p4suh|t=;}W&A-$I9DEFv@#-epC<68$31`l1Cjp<$}xh;(vL##VdO zM2uN_O`1!;9y53zjWVyx1}r9nZYduPwD?fyoYB^%ocPzfppzmq1Wh( z-2;W#LUF-oJih&&;rfNQKk(EdoQ^<$%sN>A2at~J#bJ1t=YyOMaJjh!iVynKMT z;|QT^Gn<=l+OuAk9UKEdjlEMV-VR^5q!21`iNG`1lMrXmj5g9fGREA7PsSGB_U%cn zo9$LyR0!MiQgO+Hi1IE% zCLW#DVTSh%kFKt+Pl)!&tZG*Vm!)kjSXVDSdw+QTIKa>DQ{w>k)xyR{*?ui4;+Po@ ztIOGyvIZC$uk=sjl1CM?9A@=4zb-c_nVbs{>(h2JNzR^?1y`M==ex!LM%{*rIR8kt zfp6oZc6NSAVVzLx1Wvpa3sYsA3FO0p*O#M`4;X54_%^C33bhyCx}Bsi2^{1Y;8L+( zGScnmAmymQWmYt;o5Rg0c0*X-94~uBn816X`&*uNpmPc`0U!>h3S9ddTI@Y1#j7@s z1APsf2+COli1YWsGDXERE;F z&jXuG!5x&A%7FVgNaNP3c^ELSM8{Gss}4eVx*SG01P)3! z4f2WBkrdxnqpP$BHx@jxAQi_o_I2O}Q`)ck6sVR2cZBdrxI(sN?c{;)bi)^hv!}ni zLI_12(n(JSO0vhst-6gBseb+Frocr;q7wFUj<#*^an&9h$Ay;B~e`ZGsP!7my}yd8|`Knf?JkHuTK^ diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testAlignedCenter@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testAlignedCenter@3x.png deleted file mode 100644 index 70b2edb7ba8d0a3c16025fc956865b11795b5a75..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20311 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 O!=fUh!>i;eTmJ(Aa*p=^ diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testAlignedEnd@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testAlignedEnd@3x.png deleted file mode 100644 index e7de0652284f941246c43204407ba0ee343e4092..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18373 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 diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testAlignedStretchNoChildExceedsMin@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testAlignedStretchNoChildExceedsMin@3x.png deleted file mode 100644 index 8c021540b469be95f374ed7640110030f0373b7a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12972 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 QfH%ufrea5WE2S~~1*@fWtpET3 diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testChildSpacing_spacingBefore@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testChildSpacing_spacingBefore@3x.png deleted file mode 100644 index 22ce210dcad29c7114594560484821c7309c3c6b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8614 zcmeHNeM}Q)7=Q12z}tfC%7^F_z1FWL_<`vnL~y&FRLTZQ3=sxsaepX?l`belF!V~w zGI1Ns>;oq<$Q)T>_;BOHFa+%8<}$+?$Uy0A>Ex=;C$)Kv)4FZO|9(NbVYSXd&`<#&e*tcj+j) zkQ#Nb<^!OJ77jxD;l?bqxilwkM+#a=bf6EBjlNWmSK&PPm2+$NYtb5(5T{8gB<>7q z-p$Yid}HhKe72<~ChY{N=MOH?w{Y9W?mNEI2b6S4mYZl6m=};^x5$uPp7YaALfnv( zoa*N&*RqFx!)iGT2t^2|xJgj7E|}&NA=VZ$paLL>g}WkwOyz3Eg3fb%7A+$vOEN60 z^rKlOiG^j!uwND#OF~#j%M{NsJo_TK-6ux$j6+8B6w3oL zM|5Aci+9Oc(bG{tP<^8N$OiEB3SRVd50LPzRB*pHop>`I2Z|ZRHHzL<{4(M8q_RA{ zK04mlzXUaV)aG}v@O}hRB*@s147i=nNr?J<4Nw1`3IGDsA|0@IcaI_!F~<^$t4#n1 zfYUtPW-|4!K%M?5$yMnIAn4F0LUGVDUyu4Yb&s+{c9VcX00YTgo1aTUiUV&-;ocG- zfE0-uqAbmGk4_6wTnVPFvoe67umu4gJ&4+Z;;CH2SRRG~1f{bPU}`L{=$Q<-^FdNw z_o8b=Omnluu>16UIZw}2@E&;Gd@B4xP~97L%2G+~UwOfJe)?Pc4;>A;{d&2moiUML zN>Y`RhY*)1hu@}lXS5Fvkj}QoB$HNDOn1-Kz|7;euMmH_Qgu+~g|uV8x_=rPXdP`5 z6}c|F>bf~XUeu0KlwjOe+Sp*v%{Av`4AyrmMIA24+UM68H*y1|W#y&C()F2ZyC$X% z7;XjlyqIq9*fbX^4h=05b&PQpH`XSF3Tdy-)_SDa zux{LIgqO-rT#j<=X?Q|28byZwP4dW4$HlgV(_SMSwqE{aNnX={SCS7KZtThMKjt+; zqwBSaciK~Py^`F~cBrYrr^{=EkIUd(t5=e78Q?O&-2it3EDBf@@N9r*13V)BH6qRu z0C+sv37rf8fk60)%zaIBh>8l?s=49mb5AJdOACKv?3%Q7Z>2bjowxM9y}Y{F==-9H z3ZxuX*8}Is$pYVMvqwE#(No4NCzVqss@i-?ZG2rilSG!=Rz>Gai$aS+JHC)+LKUa| z9G>~_U3rll-~F4br_aXhfu7|ANkMu7sfB06XXyM@ z*2!C8HG)YA$w=;`|l7; z%595raL*`njz_aw#ged+u94MZ>gefC7)}bw%=Ryo2R%+5yZKnLBtcB4hb*srlH)#? zK_LK9#Rw&biiin!1S-Ws`3K0&U=XGNSAh#tfGOz16krN`Fa?-`v;P|f@B7SyKb)U_ UUw&poqVPwG1nu^?MlP%LPm9eP8vpFF#2E=?$JPjv*C{Z*Cs!Ji@?p z^um|>C22uN>^b(g?q%y24Dy-xyfXfOSpy@Fh=hXnp*VvNA`i@!J(C%j<(auTtCsEH zQe>-OV3uSvYOX5w-n)fEk+X=K&4?$3P1H&8h(i}+p5P%K=9!M32C9zYqjIC+GMXkv z^TTLaFj_{A)(<13Zd`9KEs=A;)uTz0v+CfdCewli?zaxyZ*)>%kvQPc!gy|5<59L2 z10@E1opp*lIwCJ-ntj;m$`Qj1mc4|K)pLT#K2R#*tPnil(7_0njA>Ei+`$pkdR;QY ze<|(<%-MqloNSaE;U#U;O#ks!tNPp-JVA;cwpm2mC^Y(!xX1zlb zSYlZA3C5)-C_0|s!l)?XBrXVSy98|G)iG0OQJFFE!Po2)@8dOq<{mJ268xal&?vyX z1Z40I4rieP!5?lFa~oS(Y%jC51aQQlOFcFLVH!d!NJg zKsN)M6VC*Y!4H&pJP)`&kbYRoCME=Qlz@|BiD06_VTM$Yo18%56t}V>5*&sOw?GDW8>ldfH|DpDdUiBsM`kj%2X(j+TU@CE;jEIP^-w4~#aG Ws+}!*6M!=v3=E#GelF{r5}E*gMO}gb diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testCrossAxisSizeBehaviors_fixedHeight@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testCrossAxisSizeBehaviors_fixedHeight@3x.png deleted file mode 100644 index 98b75fc16230b87128ebfb9c5e7c0c6f33b04611..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17934 zcmeHNe@qj16u*|X9u>l6AnU;BnHlJejuOO@5bL#6gai={$%ba*z^#f1)M=cXR$6E> ze=$ww6i_FX#gX`H8%&9FSc$MqK|l{yV1WwQK5Pbl#C}HfC><-MzkI z$IN6#dEu7-sL#N@Ut>2kw(G9tF3ZyVsT)U z46U9n31e7h3gaxxVp4Ort_%;1lA#-uo=s|2DqL)YvunTSr)R2=p@&3U;mM^)Gg_H9 zd|N;7*(j(bd{VHMuvTGhVfSV^@I*1ZK!AV%0m%naHO44_AOxfacuN3~%#=r6Df;;r zKRuRse`~0Dq#yuNuP78hclc6{G5ng)zT=MiL!ITpB1R^QsI=ws;&WD;H|pjW0r;B~ zPQb_VpoGHywXwszkcbIT-r=aySO*?HZ7ph_dv;0m0TEYQV^{>L*#?!R$9+9>@PY__ z9d&j#A}AsL%Z&$a`K=TPg-Z`&W(Jf795e|>w5$9vpuQAxeQ^D9MlF__QiV^n>O-<@B#BB5g9Y8}66 z8Ex{G%&qk`d?nd&l^hWRwW*M|gdQAnPRkHU#5Of;ir0k)75ClpG@ht>4z+rU>$iAD z^wnLq8xoChBoNNvO4QY>u52`gNmj%TpsCz0(-(V7`g$^+L#@IyIZa+)bo-#8Xs!5x z-BsvwImyuPQY2@_wB{jEb|6}{C36IY8Lns<4`R$BWC zxC!y0|L|UL6L1r$m;%}4Uy~fT3AhQkiGqe~0-)>f%miUU09`K}H+izz*dIrz;Go*< z_lpgZN4bbI?g#G;lUa}<(2R(TzJ#Q4%iT)_Cc0Ot$a}0A9y8qg1YLg1 z@nDAgZlJV|r6HrL!KlarU{qMC;QkO(A*Mp2g6t2F3Lw>sg;V`#gPPx;z9DiJMNRty z?@Al`(I}%RS|0D)-^%Kvbx*A833L{aHG=LDjqj{+5i1E`pXGR!D>kr03m2tDfLF3JeO;V%bQt zj1l7l1Yc|j$Vy^jg>;P#0XRlPegN>WAprS`TmdKnHUw}bk?sMBM20}SP=Q^O_yA=G zsKC@9N?(|1K5631{se>V;yeHV diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testCrossAxisSizeBehaviors_variableHeight@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testCrossAxisSizeBehaviors_variableHeight@3x.png deleted file mode 100644 index 12bfc63001f2029031f9b1ccc4ee57ec74dce432..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10186 zcmeI0e@qi+7{~8Q%dQmS0j`B1a-GUpV)Rv(3mSTa-b&6pShuhr(!9jePq`n z^TIEXoi0QWaRj)~nEEg|Gq@`|`eYJw=P(!Z1169l#~nNi&zl18G4I0ndX zqb}|}?8P0h*xNdLx5-GKq^u4T*`u6$@1qL+vh{hur%x2-CjlHTmW!3&7d3bEB-^f` zcAOyP(Ilp}20q$jM=csIhU1iYCsn3IR9#BkO^dgFpq$~uLFf<|3~(brW%%EyVt<>< zA%F7^hhtSC5?MQ6V>&N=(k{ZXT;^TfhnHY(m}X!^3Ev+L`=;uHBfgH3!) z%gBT@w9s`VT)U%`+x5I53HZQ&HB2}1k zy*CR|NK7)I*?0HP($%tQy?o5U8bnhI?!$j`c5xN;&7ujbXyQtC=^4N6cqZp1V%Jm} zX~AuNMTCT)>&?SnsbxBgZaJgFIjK>wv?a*-@u2ReM^zv}Q$h4d|FCbwL;6Ug5T}k8 zWbxZ|>9(njke{8CE~wYH)!kWFrY344z1eK5kk7j}=1~C&0!+IvqLXV%52;+XigKNk zt{F=0h7{>boSt(_q~F*QggYlK&D2$8-qbjE`arko!nAdpchxzmu478yF%j?F>E;JZ z-!50!t6xG2!{Z-;48sGe2UHJK3?v(>2TU$7xxA>7{_WbsrpGrM5R_>V&^*Hzy&R@D zz;prh_Shjk(-t5|Vn4q7@vBO9Mu}$+7*dj{#F4&U94z{YN7u3cweUsV&c#8G4?k3D~!NZj50eW;v^?kJSL9IhdfqJd%*q?e41-9Eb$=Eq>YyEYJ{dcCJ?d zFvv6#mXr!~)d{hQ2Qr0Sr}-68B=cyU0?@rsSRt*f;0X!7LCi zs=c%v91So&LB)Gn?rhcC%KDkQ=fHmdG?wN73dRGb(`o_6Qw}9#xkovRGfQ`fKfD?H zN*OxV3@k{5Lc*)f~Vyo9%YVRO~?n!G8rE=4a!mCxT#{Fl)niM5JHnH*@nq zZQRk7M^=%PbJewW~33{WVKc%@G%r^8CVe% zuepHPb;3}3aZ}A&JG$@+_y8f1V`J+AHbc}HcQ`gmKi;||x(*DxYXcl2trW+bLf!#} zeW*x>9HU1sw`Y_9xelc(AsF-+j4`+?pgqoKxytW~Y&wEVFYMy9@|pVeDN?slB>?rhjc8^0;#E z_1?XEm*c+g^FE)?dw*lGHfC<(T#BM%iq__Drl<%jMTzCCnB+Kah(948bp2+nhB|XC z=@+sisaw0fo}w15;D70Y50~jlX3{(P8%oHhi2RbDh-k8T+5gG^t!ux$>{W7#JgO*P zU1Fd|epK&%eVH^;Jv@D5UY|K(N?u|+efh*I>7_sY{>S7;Mu{yn<*qa>QI#^sLUYNN z_NvT7jE)OUZl@%7(sfrP%;y-UOIWjwv&#&lz5R^fjAWP9$TH~AWYRA2dMaBa!hBjL zwWjJtg49v$c3vNk3(HScu6BUI?6@Ly9`37eei^)Sg()k<1$DP;E_JG$)u*wI`Xs~Ub(>CIW$@LSil zJJj-~`br}$mh1V=goEq;rcfLEmbX=DuFIN8dF{ZPuK5ws860^sGB|FjxNyt3>aMf4 z;?MaTFV!=;iROm#$B#aBh3Tq`D-ImMAJv_$U|+QSTCiGGIvRU6vvFrmuykpJIiu%7 zX?MLnGD zS}h+lXS9j;dEZEWh1D}%PdepvG&?YOcemqO zdwg1cKbz^lC!`=LOTpU9q;ESrW6Lzzw`OaSZ(AU>9_s(ze0*X0w)dK!tC+o0E2>B@ z_A9QQRHt0DR(A*cy*rcKtd>tBSLc*=OUGUqv=B#UKNXo3lSG0E<{|2xDat6;)2ZvY&K@yN}f@~g(wR~H2+y6n$u?Q2HtdR zdOEv;X%Co;J)E%^bKD^oW0yiK#vVOdJ~_2-O{?Y0ue;h}-~Cx^>pQlZ(4>40JscOy zyEA=jch*WR!~N`l)7|>T^NqXS2$WM1XXWxOuBMCj;lc5xoqO-IHt(2cfQ)1O6?iSC zO@}3#doO()bSWY-&OO8`Nc=-v+7RkdRd4x3h`0|VJAoWeifVl|fBAAO{E`qrT<|3GjSc({HL(l3%0KWr%2mB5X zQY>d5*W-W(DVU4!AcY61A5{i(5zIv}7s*Hgj#y9ah&47pUrS8JbTcMnn5@EN6(*}N zSv9^jsx(_+@>3P;dO?#pCiysLKk;yJSiUY#dQ@=LMoI1}lU8+mU0A-&sK^pD znU)zEL>>FjAE81oh5wqmO4#I7uZKyVs#em1OCh`Fq0n9?EuHCT5jxt}>4tjI^u3*x VhpN7_t>WFriVBMJ&uH}KzX1s-dm;b; diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testEmptyStack@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testEmptyStack@3x.png deleted file mode 100644 index 54ac8f2b5bb2c7ff4419c14de0501028292a5639..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 841 zcmeAS@N?(olHy`uVBq!ia0vp^(?FPm4M^HB7Cr(}jKx9jP7LeL$-D$|I14-?iy0Uc zEkKyjb(&!UP*5h*#Xkf{GXXIOcmuHplm@aHCoQ-C7yzW>JY5_^Dj45fGUR1o;5oeE zqx#*2C!RCC5d4|O#louhqh#fQ15FB=3}KV5YDVy=upaQ*WX0OuxP&3XGi-T+;RF!| z?US!Wbl4^_C8$QuZ93`@#IQzXb?^oW53Yu(DWzOu%$|%JCav*1m^2a%;b&m@|Nlwv nk8WT{$ACim?PxgDBH8dSo$K;BVu6`6D5-n8`njxgN@xNAcaRm* diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testFixedFlexBasisAppliedWhenFlexingItems_overflow@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testFixedFlexBasisAppliedWhenFlexingItems_overflow@3x.png deleted file mode 100644 index 4f9ffc33ab1fc0c87ba6f4df77490c1da41f1cac..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10441 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 AbN~PV diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testFixedFlexBasisAppliedWhenFlexingItems_underflow@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testFixedFlexBasisAppliedWhenFlexingItems_underflow@3x.png deleted file mode 100644 index dc22edc0aa4a469078986e181aaf4b0172546304..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11732 zcmeI2c~leU8pdanOp3`JqzJ~OO@hKLf<=lNgS82ZEMnjaSfpZOOGT<;RD!!F!(yPK zjZ(Ox=86_Y!9v`CT9?sU!M0cg7eJ&zsYXGiR=cRJebXzGQ@H=#e}{8&l1$F`&GS9K z_nB`wsX`wOk@Q%UD{?`Ssf4+E!&mJSg!oEI(Anvy#L)Gys(B3w6Ix&tM za`E%$dx9qA%zF8F!J$Q6yK~-p_~7a9Q=WV14EPXU!I+!daB+j8@Aqev3ZY*@)pb

NAQSff>M=+Sd$Z7*BtCdcwUkQ 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 Z*?}qk>wd`i0*7lDJYD@<);T3K0RSCHsA&KI diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testFlexWithUnequalIntrinsicSizes_overflow@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testFlexWithUnequalIntrinsicSizes_overflow@3x.png deleted file mode 100644 index 1b82cbb9c4b945eb70f3a75c64f401277c7fe86d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8964 zcmeAS@N?(olHy`uVBq!ia0y~yV2WU1U_8XZ1{5(a-kt)a7>k44ofy`glX(f`a29w( z7Bes?T7WR4>omgzprA~qi+>1^W&&amcnHKAP#VY<+MK?ea}toQ_jGX#sbG9_-O*3M zP=Lkp-~Y^M@?TQ7yz*o3caf-F@ zkM{c4rEC%h7}&~;E==QoSr(MeyKk3x)7CHc;T`p@JKiU})MFM|Qpa?wa{JuRcLjBt zS{Zo~5;U1h_fE*KTXLEy=zLnlbiUQMuC7*>KbFqM;qjMcOG4hkyT(cpEZocz2Mz?W zy{b~YA6u!>eKGtd&+AKxp}W@$e3#X^o7&KD#oxjD{kGzL)=jP(3>p}DbW#_r6aRF! zza-M(6;y52*C&U6oMB*GIln>djP8zVH%LY zLyY^G*d1GCln}c+wSALB?bNdy^kl=f{^lyYfACT)Bq~1VSwG*cj1m=pJf^cQnFmq3 zI^5r`=R73D4&G_no$i7XV!J;Dh%H{fN%Gp#!>h{T72jD$>^cpOin4pT&uhw2qGGoE z%S{beHbc~YeRZ<^<4kaf>CT8Q_}+sOV&&m-r;@&enjPL%5^?pN_K{k4?{Y{~oZJ0& z&ig);sQ9cLD>k7DqIO-J?N0+cV{nME7IVLwCx{Ya?@l>K_Ut|th; zNJu#EQ1w&d-QR2Lm;Yg#@+xlSDHk;!gAe%!F4r+D(f@8Ey z7%ekL>xVkUtsXWrNPdYOLhXNQpUHx3v IIVCg!0Jy0r8~^|S diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testFlexWithUnequalIntrinsicSizes_underflow@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testFlexWithUnequalIntrinsicSizes_underflow@3x.png deleted file mode 100644 index c4db41e310bb0e0c900cb4673c75d559326d104e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13240 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 diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testHorizontalAndVerticalAlignments_horizontalCenter@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testHorizontalAndVerticalAlignments_horizontalCenter@3x.png deleted file mode 100644 index 36a78c6fe719a657fddf7124203a643ba613fa03..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10462 zcmeHNdrVVT7{9%3>20B`Fcf8wR7fX-4jdCLvbYPD0kW}%NWDOZ*9Dy7vck+9E{^uf zh?7l*B2*2o^?`Hi!#B+So~7eNq=`5O{Kk92L={~O)0wiM-NLzW+7@6iwZ z>b#OI5VT0*fQ7jSwoc9Z<|HFOWtjsCEt^j9L&`{}2hlB*lIbblmYp0%cyH9C;h zSdlA|pFivCFurv+w6p$UJip~i3V-$SE0^4wu9(RPq88T*)GeL(-d=6~tn4G(e#SshI3Bd>1i00p@Vp;sO-1kIPXm z{8{D~Ne^i$D?6|*VbxMe^)b1D{fMxw0ZOcxFTyGn?x0Y(H=NlB%;|w)V^~$}tO8;b z#jgh_En0%&ty#N+>LAigpbT^5;LQLt13m+y83@fxt^#=mB+VeQ0B{Civws0JB?i4l zHM3rEgP4#dk7yjOxXHRluNhLB+b?_6T&0zja@ZC#O5w-8k1X+COzKA-MUVHpxErT` zU#&_cy2J59WaF#5a&YlKCKSj9i1T?hL!r*W&Z!-%&@_2>^GhpzPDvD2AGhGsC=4#Z zBlaWhV_FDp3c)OG#!~|RHES5G_NS3eorOuN%v?9YY_Q+G#*QYU_ukmtsqVJ}iw9mu3Lu?Pc^pbZVRL^o48p~u1O~M3aj~CC(a8= z;5rKybxxV<-6Ic$PhcjMmLE(ekuc8QmTl8!YV|T|?$lBnu8f=xZ!(T8e*)9EaoZ+~ zU&r9tK{^F4^y`3s81@<=6?bNo`gLS$>d>{WA}m26eEjwIO)dxkHhVhxUw=va8~(7rI;XLs!H@wv+N zJV64tjf%uLN$?+W)llqH0-gmS~a1KZLf5m zTk0s~n|i_#Da<8$yH!3V{>C!HggT2(`C;iZ%FPloDN`Y{c3pVKqfq#x5YK-rfBQ>&xS zYN=8eG`5&2stv<%a$%L2slAc(BF^R1L;h@yj<9K|#+H~orj%!*7XjiB5jf0Qg9D}l w{0>AFy7&Mb0XPD11mFk&i2-QzpGVQ-yvucW++FDSr2h|y`8kDhOE$jaZwtf@c>n+a diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testHorizontalAndVerticalAlignments_horizontalTopLeft@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testHorizontalAndVerticalAlignments_horizontalTopLeft@3x.png deleted file mode 100644 index ae763d07e3a1581fc51d4762eb48c62dd8cf69f5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8970 zcmeHNTTc@~6y6=CWhm4va!CUuY!MKl8k?w9A9O(wii)JcQeq!gVoZ#Y>x-h0-5R_g zsKEdx5bc8|MrvJrf<&PZBq2mzkjn!RV^JdU@;0FAFkdu~jwJRDwA_jLHJZfoZXTWwOSmyCJl`1t3~}Bvx0xP>qUc&>RLv1|V`q_vdu^@fn*kP{Y6b&FUsNjrc z>O4dNi@2MWdT7~>FL?tijX9t0QhFkTNog^|HIDjB{ z>LNlT_X(b)TMZ8alQKAQm{(e48c3W*RvOtiB-oJ9xgGiDI6kfO`xhL>XB4$#Q9h#k zHDipWC=_8_@7|Z$6a$Vf>NdWI$QD|}Q?sqHA^twiUk3`?ayW`smewnTON-wkLm14x zEx8{<7}%K_LXYADCiTI>pcKGIX-!ItWiZ3*KBXv1faCuvErCoz+$GCEvbqAhj_eZ> zR&ee^0%VXl2%ix8#rlH?iJ-tDx{D}CES!np4kRKZbs(t&P94O^+Ph2M)rmuC^2aLX Lf|7i99`E=MAHNj| diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testHorizontalAndVerticalAlignments_verticalBottomRight@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testHorizontalAndVerticalAlignments_verticalBottomRight@3x.png deleted file mode 100644 index 8ba43f05495376e29913df0e05f95262994078ae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9306 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 NJYD@<);T3K0RX{iojm{m diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testJustifiedCenterWithChildSpacing_variableHeight@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testJustifiedCenterWithChildSpacing_variableHeight@3x.png deleted file mode 100644 index f6249587a03d2daaeae91e9c0849d832a998ece7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10886 zcmeHMe^3;7Z4;O?5&CnA)q;HXaZ$#y%Pu#F9r;t;L+*@q9|5UFJf>P zS8{?8GKnH;$kEtnH3B6?2@yF+6C4BKij%0A2!ysmBjp?^B?hqXJ(zJOGdI(}I!&{8 zbF=r}=lgcQ-}gS>?|ydQ0b^2}m;0mc7>0Qz#Ov2$7~Y0qZZf3;Jx>%bTL2FD&b4s@ zR`Yq_5NN3L;?s6wm?jGTaKn*hCeRs}qhFH@js*CD4?G1HI(>xy=e_Z;1FNMzNk^>~sWp2G%i>^z6|@jz^NwLm)zm~#8Eo*f8Df0ja-55v z{4OR4HbkluVxm2V&|B``D~N^-j5!7|Ou9;1oujw^WkKF>%iWM8r_^-+P}j&^)X-b9(^i-3U-H4p z6{NMCI*|9l`ZFBz4Op!@l5(74>omL!E_3|rwR3TjLsm=c-|x|5k{5FFt2;-|P%J%d z^~UBeLI`Rra5eYd4=K`e^KRDK=6RG*V2^C1bEhO|&#My8-mfwdlD=xhmffU>-(waxE zOG9H-IJb4rk__a;L5l9D-mgbvy$JpF@uVg_bYdREwlS%j(O4w_Wd#5yR*|>9KjVm1 zneCpwX46~yt^_UN(ca zZn#|r9&YFk*|ud%LGIk~L%%lO7(l|#;kn7&XUQy>0&I70eU|cz@Qc}2`{i@9!wOCy z;do5y@C@wQ(iP0Gg661NckRouo-pTvzuM~C)lisL2VCy3-@Q0C0n);^sFDuf5Wf4X z%yaJsCXYoSwYc1^G9aqzT2(B_KVhj)QO&vGhLpaiujn?H`9RGoXv-_5fmepV1Njq5 zYBi~isiTd}>2W_leP;*KvDrU}F=PGBEobe!W@Z5tS2L@1YrofXFOIYtDYHa61iNo_mrS!?-!Q-TFb)vIl@t^^GuY}amM!Ceu9Fw%#x<>NVH$^UAUG*W^ zOf^#(H%LDMU}1tb&#dyRux?E()lL$>Pk4*NIWqpOJ$$70Lh zyhnjE`I~)GsZhain(DMy2BdB%x|F~(O=Q=GqD(ncuGva>-~gLj9T25;D@}AfsSXt? z`YID0rQmybwMkBxB(E6Pv@EU$~IacY?RH4Ys#$s__!vG6ih)fV^SR-)if88 zn2L@RR-#16#UlksZ;)T{uWcXUyJ61RTSRWrbe>50mXBzZA4VCPfov+Dy?qXc(30|* zoa^o%)*+N~NGtKFJX1VpV?I<@&Y4Fj+TY0?oFk5duG8RQ=RSEEJnTq~ iqSC2M$bU+P2|Ty!glEGmpOu5xHCTcnNnazFivA4)FS7~& diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testJustifiedSpaceAroundWithOneChild@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testJustifiedSpaceAroundWithOneChild@3x.png deleted file mode 100644 index f97ca1ee1fa855889a25450edf674bf6d91e94b3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3706 zcmeAS@N?(olHy`uVBq!ia0y~yU~U1jr*W_W$+jJCWZO_Tj9YDJr z6x0_8JcAitIcoT5u#Bdb(M&X2wv3jFq*NA-{J@&<|NlQPgr$I0;1^I8_;$1c9Iag^ t2#+>8M%!YeO;k|JeY9~sjQbpo{4+(Wot@V!&Hz?~44$rjF6*2UngF({)13eS diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testJustifiedSpaceAroundWithRemainingSpace@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testJustifiedSpaceAroundWithRemainingSpace@3x.png deleted file mode 100644 index ea5c8e4db7d5757ff1afec85d47ffcfd6055348f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5741 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 diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testNegativeViolationIsDistributedBasedOnSizeAmongMixedChildrenWithArbitraryFloats@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testNegativeViolationIsDistributedBasedOnSizeAmongMixedChildrenWithArbitraryFloats@3x.png deleted file mode 100644 index 0ba9ef52265a2be501a48b3d5562d219adddf76d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 30770 zcmeI4eQXnD9LJx#TaVIpu}enNk!2P^SXdXjCT*)WEMc#=#;1Sg9x8FO5B{Z+Asw7=s z<=v(K%x$WEzL}5(%h@6XI*L`gF|X0TW<6btbYZIy{Zo)!v+osoV~q_%geauOU$K6V z@XPhJJ4U^BNgs(1zIv{I-Xcvt9e8x_uxn`XgWsm7r}w)0H9P(EY|%^ZxSHA`H&1L7 zGpr7Gu+V$@(1~|Ge?z{#Yjp4nMcza|(NgJ?3d?sj@+)UNEh`i0ykoT%=fQ*aE4|*aenbzqUOXdA&`rI0crdz!_Ap=I+0JfB31O`r+~L25YwMpy zvoZYUUPU7`bxvt-U)I1t^N8oDM`nrK(uLeu*3wv=FRDM0NYf|Uj+QkH%#`=a^x)^V z-VX%lst;+xGn@62sJ`N|GI^?R_Z(IWMcLWiaARU-)!5b7hF?tN=KK1X@IzD_UnJQ) z$(nkiO&@emUAfu4l^$Gn?%@j=?PSX`TD-8Kc)Pjc6`^?SIzjYs?V0af+!~1{6t@O$ z4cr>66Gxv5#R5SEISMh4u?9wJrg1LRGSo6421P(%EFe_0Z3N!~e*8DV+jx9xbz+#$ zfb(Bp-1SOi-pcuz3;*7f+V}gisNN^*4G5|7gW3rnW z0DugD41f%P446X*$N+{WI;RAe!9VOWsE%J>LEjH>gS`vjzi8*1SVL<^;_=ljWuFpK z(#z_3Z>Tt%5W9HxQR%bWXO1krRk>sbZ>iLj(5;KZe%?^%_DUT~4A#Sxg|Ir)6&swg z@{U4Pe~`wT*(gZ$=ktH$-H`UsfmDu$bGVCCz4rTsX`GzGmyhw*%#SVh(A|A+^JVv{ zf246Y_Gm)khSnzD$SHfC=AD^GoL=?Rcs3s~T^pUl*Jn_aJ9m{|C_3z`>G!y7@Hj*b)^Dbx!jqe)~!r$aJAGD0#!GD0$% zfdV8WBqJmvBqJoF=^X%&jF60wjF60wjF61R2q>7Y!yG9lrj55mQage&LNY=!LNY=! zLNc0r2T(>(Mo>mjMo>mjMq>ov+J#jbR%!Ut@lb&2Nd!>(L9c{IzSo!Hk diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testNegativeViolationIsDistributedBasedOnSizeAndFlexFactor@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testNegativeViolationIsDistributedBasedOnSizeAndFlexFactor@3x.png deleted file mode 100644 index 43440d204554b92efd2b0a47e926f0493387b026..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 30791 zcmeHQYfBVS7@nDSYd2k4i;Be33M{l7mTjdR+O2VP)YS6?aZ0o({!pIpgbSOnO!+&#%G@AdEfKS zyjYpzc3MWpjT8jIlI60m6a+(~x|xQPZ@MNm-6K13+e&Aq(9jm&Nj{i;u2tIvVN#m9 ziH@37g?t(BwJ*;ldx>o7&O?4o*Y@gh`m2rm`pM_?^I7&qxus(FvrCp1Ioc5Hz2(hz zbQi4;CRd2HDg8IU#C|Zg?H5GJV6rC4{_ug-d?TaqkSpZq@E#l3~+{U-UVlXGibRr!bD_Qft&$316%!q3?Ku@ zzz_f#7!+^@kO5?12!IR>3OEDE05UKHKn4Z{oB?D285jZ}1A_w205X6K3;~dVK>=p~ z89)Yx0LZ|gfHQy$AOk}HWMELh89)Y*fgu1gFeu;*AOpz25C9n%6mSNR0c2nZfD8-@ zI0MKqSjceWmU47qMcIgRM%x~~w=_{Pmsa~b|Jgs9q?kRAY_*Fc9k1b+;+Gmo&*_rD z;UhIC7y{aXoJ6McNcr2B{ne*BS|meAd+V8^>0H~Z+HN7$`11;@=W){o>}p4>;Xmfa7QPdjiiwxaINo7$&+n|wcGE+lYtlS3}0p=DP`<=TOg zz+X+>KEmK1Qcvr+(t_Fb9sg>!UJ}?kBGMHR=IhR8KjEU;(>cZ#&z+6xp=JSVCkY>% zHc|;?U#x%4&85lY1vibHI7?GjnZx4bq(Ig4E{4BWuQt=enZ;>;_N~iQR4FCgG*(v> zo$2736)mxxaH!U<598!1uh!)Gb#L50&Q_=d?@r*RF+9{%TUXHTNuD85E5TNM?0uIaC2vKowYR z(-Hwz+bDd{*g#9Qs6lDAFw|9{9BZ#yu`8pu_$ptDl$@kq_vFg*byHE@@zcorRxjC3d9OEHXwsS z24%v!LQevyf{T%e6^Ipx6?k!x+5%z)VufmlsLY}=i#MzBk~>ua`VI8&a-iQpZ;gl* xT;_-j3Kq8laA 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 XChA`0N27E4pK(@i4hN%^%8P#k>c!C) diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testNegativeViolationIsDistributedBasedOnSizeAndFlexFactorDoesNotShrinkToZeroWithArbitraryFloats@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testNegativeViolationIsDistributedBasedOnSizeAndFlexFactorDoesNotShrinkToZeroWithArbitraryFloats@3x.png deleted file mode 100644 index bd0220306019934e40b19326a08512ab1dc69fdd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 29674 zcmeHQe{2(F7{2e?mD^gRV@We~*=_+cV}~n}$c*BSQS5$%YRFs;2<9R}vY>8cY6uFu zsR_ZUn}4jC32|T`#yD$a{NXv;kmjwSN-p|! z!8rYp-Bh)$nd6Gf^^I(ftX1gFf`;J3b+qN_rZ+NuxzlX*_YZvgOUO4y+hf(ijdlCU zujjvc?P9>2wK3V<8*Zz8d&vh+-t68{kn_Z6=dRDxsvO~+f>#XqulE1`^GNUMTeo%z z`CVk4;z~#_xCWA`MJD27XZ!9TL&aSc&Z$uRuYC`l)#g2d%om!+kd$p&T$$S`D)%|B zAC|Oh73~S_$O>;PQr2_me#=I?aByz&ZquT_Jhv?IZeypKJYQp-i0o@BdaETbTfXh| zY_T`yEM3?1xXam-biX$ewoI-**WD6#n+9d!Gw$XqJ60gNBPKJf7%ZR_s?xvW%*%w3~r#8 z1KeQT6>tOGfY?B%3WP{epE2PExB+6l+so}K>UD-%?*GCafVK|+S|4XA1HUg1QRv*(XL<${0g)Xh|N zw~IZ>FwfT?c)s*?3&1nMFWpR{fYky{Wng>8R}F;tKi%L9F()c2Z!$e{t-Y$+`BP!r z%JgBaA9`a6rbkuUE@?H5?Vsl^8oy~T$a|O`C2@_Yob3DZ5<4i0_c1++9X@Yt_`$a65Bh;A%&ZL68x=i0znCF{L7tK>~>c5_vny zC6r63QUMMClL00JC=3WB5J&*Oz}tbhgXUP^Q_?^>*d>mVdSI78>VZoIg$)WD$^ll} z0Ko>~!7hPa0=oou3GCAUon30Jpv#u$=U-Y?bDZPujq7WbC%<2t%W)q5)Xe%VPtA7R zHCkEnG%IgZC3$r4hajs=6a$V(i5)zV9~-_Qu);@0yJoACbku)RIL1!j9{G@+l2OrW zzFTRd*(5{D?6ig+dHlf3?70V&lx^Wa{5#v5*mB!dT49%C29%Q%xva-DHMxWx&oJ-m zd1k{PE7{DC&DsHdn%Wr+*@!9~ks>%9PS3bEPGsRqM|eSa$&B4pYK)kUi4+rQW{T0_ zL-vA{5qUaOG$2n$afFIAbGne|nnP5ifB}HLFhEe18-N!8FQAMJ&~?E=~bo}S4x zh-*M%fW!cE#L!qEF~E_6Bh8#H=o7L*Vn7W5H2_n2(g>0`@{6Acbm|Nf_wUa3LUtfD{5!2uPXO0PF?W3sYYKdr?)aIr{e(dTEYV XChA`0N27E4pK(@i4hN%^%8P#k>c!C) diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testNegativeViolationIsDistributedBasedOnSizeAndFlexFactorWithArbitraryFloats@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testNegativeViolationIsDistributedBasedOnSizeAndFlexFactorWithArbitraryFloats@3x.png deleted file mode 100644 index 43440d204554b92efd2b0a47e926f0493387b026..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 30791 zcmeHQYfBVS7@nDSYd2k4i;Be33M{l7mTjdR+O2VP)YS6?aZ0o({!pIpgbSOnO!+&#%G@AdEfKS zyjYpzc3MWpjT8jIlI60m6a+(~x|xQPZ@MNm-6K13+e&Aq(9jm&Nj{i;u2tIvVN#m9 ziH@37g?t(BwJ*;ldx>o7&O?4o*Y@gh`m2rm`pM_?^I7&qxus(FvrCp1Ioc5Hz2(hz zbQi4;CRd2HDg8IU#C|Zg?H5GJV6rC4{_ug-d?TaqkSpZq@E#l3~+{U-UVlXGibRr!bD_Qft&$316%!q3?Ku@ zzz_f#7!+^@kO5?12!IR>3OEDE05UKHKn4Z{oB?D285jZ}1A_w205X6K3;~dVK>=p~ z89)Yx0LZ|gfHQy$AOk}HWMELh89)Y*fgu1gFeu;*AOpz25C9n%6mSNR0c2nZfD8-@ zI0MKqSjceWmU47qMcIgRM%x~~w=_{Pmsa~b|Jgs9q?kRAY_*Fc9k1b+;+Gmo&*_rD z;UhIC7y{aXoJ6McNcr2B{ne*BS|meAd+V8^>0H~Z+HN7$`11;@=W){o>}p4>;Xmfa7QPdjiiwxaINo7$&+n|wcGE+lYtlS3}0p=DP`<=TOg zz+X+>KEmK1Qcvr+(t_Fb9sg>!UJ}?kBGMHR=IhR8KjEU;(>cZ#&z+6xp=JSVCkY>% zHc|;?U#x%4&85lY1vibHI7?GjnZx4bq(Ig4E{4BWuQt=enZ;>;_N~iQR4FCgG*(v> zo$2736)mxxaH!U<598!1uh!)Gb#L50&Q_=d?@r*RF+9{%TUXHTNuD85E5TNM?0uIaC2vKowYR z(-Hwz+bDd{*g#9Qs6lDAFw|9{9BZ#yu`8pu_$ptDl$@kq_vFg*byHE@@zcorRxjC3d9OEHXwsS z24%v!LQevyf{T%e6^Ipx6?k!x+5%z)VufmlsLY}=i#MzBk~>ua`VI8&a-iQpZ;gl* xT;_-j3KUODeE+-Gj&pi=c^RXTQ0Y&|Ha{y z^7fqbJ~`)k|IhFFH+)>TvMMz>GnwPK)M}S=6~~!;%9d!B-wEY>_p7`kO{=OZxW3`6 zQTdl7kL%4Qj>{=lHnPH7D9UeUH9Bk8$a`Mil$~4t@w~QIUYBh>(=qa{ysxNsmal0c ze_c4+xvp@2WqJ7O;q&V{XyxVVuFaOpWzOrj9z5*k2yaSEvyHif4<>d+HtZKl?7xwm z)Q+3W=T9E|Q#xafyc3QMl3Gvib0;*5JwkhC(l2z&`_kCXz`x5<-R4sDFpl7H>CU)! z{QJlU;@84pX7bQS4JZ9=tF!Im@e|*U&(Q|WJc?(_d;Meek6)TxDoXczY!0eiQoz!` zZJ;$ot)DhK>T=5$_)^>@o<70c8-8Q!32jJX%iQhrVj~KMJD>Tn=IU2u=<{}MQY{6+ z;gP^M@{IhXywlVmy)2GO1J(>*;O&bOyf*J(+0B~XsS(GDi`G9{vU8s~zcx8KAG)-= z^@#PhQ170kQNWAh<)K4;3C6bPO>m?FagQX!kqHl_pFS^z62*BPj-8BMJiPndM zGXu^HI5XhPFk%%OY-{pYZ~s%}7$F=tIeFUCy_(~e996zeedj`9I>)8(haMNzY>afh z5Uj}C^ck~iQHMJ?c+tsPCvA4Yn>R}l_%Jb^x$(YWbYl>{QFdnj@Z2?)wWhdt&2pEV z&y8oa9GV+*bw;nMXHJTHbVmn!?RN2>S&WwTd*YftmrpZw>LKcS+AbalrLz%}=*VoQ z&$7XIF3w1tps$ta-oC10rbSBx@51QxViQ)eB!V6bh#n%{RbG z(hHO8kY13}v5-Q&K)o1rDi%@`bUJi8BN%KbjwnGzii#8!DU%z(UI4t9%9}a>yv+Ha zj6l0a=neJ)_5$_-_5$_-_F`=OfxUpeF!dGKi|nKTdjWd^dtq_|*bCST*b5w923r|? zFR<0Y%LoH0T)V~!8wOHHMo30TMo30TMgxC_WQ1gdWcUgGKE7*fIb=BguCLjaHS z!F&HNiN3$Ezrvs?nscFKdiu51&7Y+s`q|z|&-m=jxrV@zP=j+nWVi%Tbgv731&TLY_3Lh3UujSWBsUy2li*oKCwGgmJ-z$CW8 zVnQZE!~v$Tv~^8PqnbwpY&4OKW(+)qfgP~e`v3o)@;O^zd6fVvuijo^53qP)@IghJ&A&SvXQy zc*2%xIdTdZMAS7fH1;$cJQbpiz^ zWlu+M4+;0hQkB8e)z4*}Q$iB}L7NoD diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testOverflowBehaviors_flex@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testOverflowBehaviors_flex@3x.png deleted file mode 100644 index c602d38886ad043ddf253cc8969aab96876f29a4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1852 zcmeAS@N?(olHy`uVBq!ia0y~yVDtjAr*W_W$sLOhJ_S;Y#X;^)4C~IxyaaMM3p^r= z85k5TK$y{WnqdM^P$tvGKLkiK0Wk=81F;5_2C|uZ^4ZpH1kw?nE{-7;jBl=8i?GM>avr$fo+ZJ4HfkZbWRyqT>aIwysRm&4WwKNEl)(p6wI{57KwC$hI~uxF zP7GIA<$zi3|Np(6#g~A2EEJT--j3$5(E?$#{Gw8E3(8^Ny>EQToIe?u(-=Hm{an^L HB{Ts5;BPa# diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testOverflowBehaviors_justifyCenter@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testOverflowBehaviors_justifyCenter@3x.png deleted file mode 100644 index 74b509f6ccd553ece526dcd5a2e6387d2c155e64..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2693 zcmeAS@N?(olHy`uVBq!ia0y~yVDtjAr*W_W$sLOhJ_S;Y#X;^)4C~IxyaaMM3p^r= z85k5TK$y{WnqdM^P$tvGKLkiK0Wk=81F;5_2C`WVes_PHz`(%r$J50zq=NCyG{Za= zN1nsq{?FgHBwSn2pp9c)Z+dFihws1l&EH?kc1$Ntn5}Mpy$@5hr^ciD8ND}o#CQxQ z6?A>kdvW&vN{zi5>O3n9v>J7`etMH`r0My8=DL4T%ciK!Demo={XTR`+!SFp5s9e> zd_Trm*Q%)&mR>h_v48rdmg1b~`S;F*1Xcz5NdzQ>FhyoL$*ey+W6F`Md)or*^p|oz zzp-t}`uUxUzATz!u;9Q7mR~^%M~ZWgEm2wbPKxdC_n=t?eYvkM&z`B}rGJW(nXAW3 z!P~dv@m9&nlXmR7ZgA@TQj>==x2JviY8(i2gF`%5OT{{{9kGWO{EzbzKDRNqw#qoz z^`)z2qC;aKXUa;>!aZimK|b zm;2tChb*_P_0LaR1r7%dP&k+>_FYf&@p|+s?yv^bqnECqcY%AfR#V{7POu&2yv_fr zHGM6PZ~OZ4tdHnY@uw|}tZu3kmZ}~3c&o?LGv;o##8Zezy?_0hsR8ro0)18|8;Bk2 z5--$4!pd&%%$4x4+H|GGB5t;!X6Nc^-o<|)9`%g37lwQE%TkAq=MXzgd455{>e_O1 zV|aWyOq(TeJlhx)Ve1p8Ks>7Z@^$(mxJUPiaD0pb+p)XN@joQ2etk(>1`n$fLBfwJ zAQ5KT^9kZn)!M&4A~26$n9ig)4`Rn?q8LpSkkn86M8V_vfS-Zk|9^oOGKYZW;4e@) t_;$1u94!UGHO6QuI9fH1gsKr#3jSjDzVY+w4M$Kj(bLt>Wt~$(698-%*~kC@ diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testOverflowBehaviors_justifyEnd@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testOverflowBehaviors_justifyEnd@3x.png deleted file mode 100644 index 1efcebc1ccc2f55cd32ccc48e1ee06423d2dbc9b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2723 zcmeAS@N?(olHy`uVBq!ia0y~yVDtjAr*W_W$sLOhJ_S;Y#X;^)4C~IxyaaMM3p^r= z85k5TK$y{WnqdM^P$tvGKLkiK0Wk=81F;5_2C`Z0vrS$z0%>kf7srqa#y8g-yI34K zTrTeVzqESV&XTX9ZSKLVS&rtrY`Opbcb)kCz}ww{U++x0@&2>(0)-7LA6@qjnD@v2 z@Ba&WI*Zhp!p{j#X)?OV;H`W?pd$QUT85h1PRUf^*>RWqq$jWFI=u|7x|bRxWHk;GD~5O-~1yg=8Jt6 zSKYtkoh%e8cq8QFYgLWdDV=N*QjKi~xYwVBxO4W6FSE+-fZVC})bxGRCD)l54GRS` zI7}QZ=Gt|7=DE#u`?_!E^kXWklpsL^_o{f@Y=}F}Hoi1{y94A-pHtcQSeJGKL(3T$ zS{Y3RR<%Nt@AMe;zN#(O@AV9EO$a`^emcUd`g_d$!S2jSx}1Hh5aiAoQ?BpfhKJS# zmWL(3R6qePb@lhNI4MwoFYAieM|d@^B6l9xoi~pxyT0Wy$ejk7>np|Kp|ybX&`U^w zo2>eNcCQI2z5)tR6G zpRHB5mj&+CiicY(A?_Sa7>%O|V~`~bhX?!&4FCVvbv)h!EEYLI#p2u1LUFWE1l2;L ih2m&!IU;LIV4?U~&ilr4&l5?YMx>{!pUXO@geCy_1f_le diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testOverflowBehaviors_justifyStart@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testOverflowBehaviors_justifyStart@3x.png deleted file mode 100644 index e6b5ab6e493eea704870f557ed63f627d628df41..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2423 zcmeAS@N?(olHy`uVBq!ia0y~yVDtjAr*W_W$sLOhJ_S;Y#X;^)4C~IxyaaMM3p^r= z85k5TK$y{WnqdM^P$tvGKLkiK0Wk=81F;5_2C`XJW;?$z1k$CRE{-7;jBlh>sU^8)+g|2#E$!ZPs3D;1^wRn$QBQ>;&WSl<3sW53&OO`B36aXlVsaWOm1gFVdQ I&MBb@06}RDivR!s diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testPositiveViolationIsDistributedEqually@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testPositiveViolationIsDistributedEqually@3x.png deleted file mode 100644 index 50fc7d1f8a71225e09cdc1919c445eb5fb967631..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23546 zcmeHPZA?>F7`|=cTC`ViCJGlbaoKQAgo5qdRANC;nZ>H8t8Ut|0cmag$RviLVv(iW z!XGx2FEgk{%2b4A%4B|&vSvS&xm4>wQ70@q=@jj>iUFZJ=XUq@+V20dqUD!qZuCpU z_GRmL5X6jk@JEnYm8?YOYWsEw$~KfYO<_^<7wAus3_}u-tXS(bzN-jV=%xI&MBR^j?#?=RDN=WQS$ZXq|ho|B7oe^S8BWwhqa+Y(`UeDte5W zWl40sOlyCgnb_&@Gr5=gx>ln$BiT(CJ^p%DS({{d>fXjv*O?70 za9S3)Th; zK-vC*U3xA>a<*w59^8w2KWKHUItq$+wR^qH{IrABH}+&7#8a0!<-x#}ZdK2H{+&N2 zZDjqqyo=g7Wn;F}pD$Obn7}9(j}~_BKZ;{^fJ~rwU-ldkh~gPg+UIDaH^rE4y`G7QeS=7~DJ9=pmA3bGfH9UsC1pbwAe0znAIQUIIAmBIoGJz5XbdwJV_)WH+{`0sE{3Z_& z@SET_Svr7jf^LG}gbf$|-WC)~RvnRhfMN;7lBL6cS}gm<5roedHuYo`LA;fRzY;Nc zEqM|_h(*aS4kpHzNQCq6)QtTR94+Bj_RIwZAy+5U3kCd~M>kYNh|w1H4E{0`t-BRE zPw2*T9NJDc1&?{CGm^Jq#$Z-!bXKgQgZG_3BNwrVvb*7V!t}*U^ue32QS=Lbb@taO zm?Xx*46L^!15J2r_(Eu03mQ-xLz+kXw zfWhEODmnp!!Jz>L0}KY}B)3ino#d1ObdqBQIsu&oodliaG6HlGbQ0Fx0ZD{)H@nir z5&`RO77frz&`Hoq&`DT61ULYj^4tzM`o=oEIl$IR(8)lKfS(Mo0{kSqyNBQBgBL~M nMG@HVW-|hG5_Iz4{iJ8oyJ_uBo3dN*Kj+TMT#?a|uHE-H;85K; diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testPositiveViolationIsDistributedEquallyAmongMixedChildren@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testPositiveViolationIsDistributedEquallyAmongMixedChildren@3x.png deleted file mode 100644 index a8d657742e36451a958622bc133215ba4b450c08..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 31713 zcmeHQe@qi+7`|TNL^vlT6M->>p%E2qK_imjI0%Y}zv2+;FX#}4WDyv+NST8xjIjX| zVx$e~5a%S>X0VI=;fBKL;zT;>f^p2v35chnE^5&YSVQ++YZkd~e=pgdq}OY|zWMI` z-tWEld*0`JbNz6`y2NRo0iF~^O-ovpu#uwNOw!@Oke2(wr!3^8DB749Pqp?04wEla z3s!9|qNw0y(xF&kh|rS8z}$rODdbF(Lpo{5Td4CaeNHf!e|GmCMR8P8LR?C*;=xaG zd11*fD7k)n@6w{QDfLu9b?%aZP4P1_`^u8Ovplp|PO2(~*$*0yG_YMf+a(OMwuw=1 zznNWI#Xh6n*>;t^m65i&Lsc=zva{!XQrZ$3q$Dr)ZV|WcX;jPw&lr{9tVQ>PXSdF1!KK8uZ?6T zwe0nGD9_W$SN7ZP%vIZ7el@Qo=Fa7lhn?c1Z)lI6*--7{7=Z3vsL7AW2U;Zg$n^BH zFR?$&NNw#mAMF(5n5^b#q9W}@d)C_S)@9s?>2z9#Z;2zFTly*Aeb@c2G>&|c)1AT) zGo~|piQd~f+KPWWquD<{L$bNiVemP2-Bh-$s_xJ%i*97$Gw}|8O{nTXrrV;7Eivz; ztDSRn(IH=JOnb;wyj|IF|M$YX`8qPpojp8VBb4)WNbLBKG0LKnW|(xI`+eIS`$!aD z84~sF?%TF|jgbw~G#M4MiQYz4c++x~A*);R6hS0*T@rq&ES>(Qe{iVfV$ls-_cQT) z#<$z+xS!r^^tCk2tfgxt`Nt0VA@OSaIqmk>#qqO&<6CEuVICwZzG4b$7P{&tM#ak` zW@(y5c4q+T+-{qu9qjrj;^XMfl9n~ul5b=SRYJKSCfDRxYUVatvz@a^raswv#3(%4 zGkSXX@!_b>!e`=#^p)25`77Zna22=;q6(r479cD@1Z)AT0ILuT2v`ePiwp=E5Rzq* z{~}pNvJ74Yyb35dP;g*tC3Y8VEr|X9FtMNi$3!AeDQGtj?;!5456!8Zep7ouh0k+s z&L3kG?uNkUMV-wlUZJMX`*tjo^+SGiH?Ru>6F9aYksTmAKz4xa0NDYu17rsP zhW`Kz7wj^ol1B{GNY4TQasqN9TbxfEdXoMzzswS*8U&P}eVR4WbhT&gm?S9$rFdY^i@mU3zZ zt8#K}r_^JvLYeyYtiee&pN=cBno^f5azWu*VRc_fpiC2v=N0DZuEm|7y0e<$lJ{J7 zS8K;yx}fxJykg<@x&l`vnXp*b;n(}Bwa4%KxLQo$#VM}i>7|(yyO*DLtz-2w+2oex zcy5cpH?$`HO%~SBev_XM~aPU8OMZb01l85 zkP(m(kP(nkz6S-C5iBEEMzD-v87J4(0y3g%7p2lDm6lbqVPl#G%LtYcEF)M(u#EDu erT-1fC@7izzofZOziyNMgF9)(x`ftvZTX+l!*uHa diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testPositiveViolationIsDistributedEquallyAmongMixedChildrenWithArbitraryFloats@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testPositiveViolationIsDistributedEquallyAmongMixedChildrenWithArbitraryFloats@3x.png deleted file mode 100644 index a8d657742e36451a958622bc133215ba4b450c08..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 31713 zcmeHQe@qi+7`|TNL^vlT6M->>p%E2qK_imjI0%Y}zv2+;FX#}4WDyv+NST8xjIjX| zVx$e~5a%S>X0VI=;fBKL;zT;>f^p2v35chnE^5&YSVQ++YZkd~e=pgdq}OY|zWMI` z-tWEld*0`JbNz6`y2NRo0iF~^O-ovpu#uwNOw!@Oke2(wr!3^8DB749Pqp?04wEla z3s!9|qNw0y(xF&kh|rS8z}$rODdbF(Lpo{5Td4CaeNHf!e|GmCMR8P8LR?C*;=xaG zd11*fD7k)n@6w{QDfLu9b?%aZP4P1_`^u8Ovplp|PO2(~*$*0yG_YMf+a(OMwuw=1 zznNWI#Xh6n*>;t^m65i&Lsc=zva{!XQrZ$3q$Dr)ZV|WcX;jPw&lr{9tVQ>PXSdF1!KK8uZ?6T zwe0nGD9_W$SN7ZP%vIZ7el@Qo=Fa7lhn?c1Z)lI6*--7{7=Z3vsL7AW2U;Zg$n^BH zFR?$&NNw#mAMF(5n5^b#q9W}@d)C_S)@9s?>2z9#Z;2zFTly*Aeb@c2G>&|c)1AT) zGo~|piQd~f+KPWWquD<{L$bNiVemP2-Bh-$s_xJ%i*97$Gw}|8O{nTXrrV;7Eivz; ztDSRn(IH=JOnb;wyj|IF|M$YX`8qPpojp8VBb4)WNbLBKG0LKnW|(xI`+eIS`$!aD z84~sF?%TF|jgbw~G#M4MiQYz4c++x~A*);R6hS0*T@rq&ES>(Qe{iVfV$ls-_cQT) z#<$z+xS!r^^tCk2tfgxt`Nt0VA@OSaIqmk>#qqO&<6CEuVICwZzG4b$7P{&tM#ak` zW@(y5c4q+T+-{qu9qjrj;^XMfl9n~ul5b=SRYJKSCfDRxYUVatvz@a^raswv#3(%4 zGkSXX@!_b>!e`=#^p)25`77Zna22=;q6(r479cD@1Z)AT0ILuT2v`ePiwp=E5Rzq* z{~}pNvJ74Yyb35dP;g*tC3Y8VEr|X9FtMNi$3!AeDQGtj?;!5456!8Zep7ouh0k+s z&L3kG?uNkUMV-wlUZJMX`*tjo^+SGiH?Ru>6F9aYksTmAKz4xa0NDYu17rsP zhW`Kz7wj^ol1B{GNY4TQasqN9TbxfEdXoMzzswS*8U&P}eVR4WbhT&gm?S9$rFdY^i@mU3zZ zt8#K}r_^JvLYeyYtiee&pN=cBno^f5azWu*VRc_fpiC2v=N0DZuEm|7y0e<$lJ{J7 zS8K;yx}fxJykg<@x&l`vnXp*b;n(}Bwa4%KxLQo$#VM}i>7|(yyO*DLtz-2w+2oex zcy5cpH?$`HO%~SBev_XM~aPU8OMZb01l85 zkP(m(kP(nkz6S-C5iBEEMzD-v87J4(0y3g%7p2lDm6lbqVPl#G%LtYcEF)M(u#EDu erT-1fC@7izzofZOziyNMgF9)(x`ftvZTX+l!*uHa diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testPositiveViolationIsDistributedEquallyWithArbitraryFloats@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testPositiveViolationIsDistributedEquallyWithArbitraryFloats@3x.png deleted file mode 100644 index 50fc7d1f8a71225e09cdc1919c445eb5fb967631..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23546 zcmeHPZA?>F7`|=cTC`ViCJGlbaoKQAgo5qdRANC;nZ>H8t8Ut|0cmag$RviLVv(iW z!XGx2FEgk{%2b4A%4B|&vSvS&xm4>wQ70@q=@jj>iUFZJ=XUq@+V20dqUD!qZuCpU z_GRmL5X6jk@JEnYm8?YOYWsEw$~KfYO<_^<7wAus3_}u-tXS(bzN-jV=%xI&MBR^j?#?=RDN=WQS$ZXq|ho|B7oe^S8BWwhqa+Y(`UeDte5W zWl40sOlyCgnb_&@Gr5=gx>ln$BiT(CJ^p%DS({{d>fXjv*O?70 za9S3)Th; zK-vC*U3xA>a<*w59^8w2KWKHUItq$+wR^qH{IrABH}+&7#8a0!<-x#}ZdK2H{+&N2 zZDjqqyo=g7Wn;F}pD$Obn7}9(j}~_BKZ;{^fJ~rwU-ldkh~gPg+UIDaH^rE4y`G7QeS=7~DJ9=pmA3bGfH9UsC1pbwAe0znAIQUIIAmBIoGJz5XbdwJV_)WH+{`0sE{3Z_& z@SET_Svr7jf^LG}gbf$|-WC)~RvnRhfMN;7lBL6cS}gm<5roedHuYo`LA;fRzY;Nc zEqM|_h(*aS4kpHzNQCq6)QtTR94+Bj_RIwZAy+5U3kCd~M>kYNh|w1H4E{0`t-BRE zPw2*T9NJDc1&?{CGm^Jq#$Z-!bXKgQgZG_3BNwrVvb*7V!t}*U^ue32QS=Lbb@taO zm?Xx*46L^!15J2r_(Eu03mQ-xLz+kXw zfWhEODmnp!!Jz>L0}KY}B)3ino#d1ObdqBQIsu&oodliaG6HlGbQ0Fx0ZD{)H@nir z5&`RO77frz&`Hoq&`DT61ULYj^4tzM`o=oEIl$IR(8)lKfS(Mo0{kSqyNBQBgBL~M nMG@HVW-|hG5_Iz4{iJ8oyJ_uBo3dN*Kj+TMT#?a|uHE-H;85K; diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testPositiveViolationIsDistributedProportionally@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testPositiveViolationIsDistributedProportionally@3x.png deleted file mode 100644 index 573dea9c820b38e907bb5b73127852a0f89b68e4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24670 zcmeHOUr19?96tM_O>=QAu~-8)A(tf+C*IMN?&|g^bSWm*|&-#kuCY{GrBpq_nHyp%iV{cIdc z3TCx<_c{kp%>@qj6sumGBMPNjBN)u>tdSb$2zF#vYYL?Lnb<2Cah>tCAIdlNRh!!S zV}8>a?-d&w*YJC=hGB!Cqy5G`CU;D~xqH_R@SI017|>TLHEL zjA?lE+(`ixGAIfc#@|lWk4+w`7#3GELo{l9$y9jXX|&s}KD=>z=Hixc#wZ+3T)UVr zH|p#0_s0CjvoVwhstqQQh^-$QZ#Eh7G+Il^or;WPS%1yGkh^#GXD;FI!x{taJ~sYM zQJ+=T?>ZUI8!bMi`7havHY+V|I=*?OZoNFUwMY|KG`Zp_RuLWnX~UO5U&QV6`FriM zdkA=OAdabm#mQ|(unMJ5@Hhex5BrFmRNFwSKxFZvCCFM<#|1r(jRZ#kTQ}@EvCD@& z5mk-wRsL&V8$e#sp zV6%iL1Bg*ZjIJL=_tamNJGywflr{2MRo?aVo7){N<+8yFrKRL!|3I6u@u=;ZE#|^y zR^I1Kp8wP0^B#M0_j}MFP5n$f)N;tV3bf(!pxS;u>}S*%oOLxCS%wI1meP0&pr2+-E#*1^Ur)p%DuGQ z^L6_^@AJIxxo^|fE!p9rF`Lfi#)rHxaq-!W{lKv4= zl~Ywd?mJKkHKg%Tbx9awG&sme4+Lm(-Fgf zKlXA2_YwV{`$CNNhO_Ad)5Ae?Y2u}ll;?@;{%NTx?ZkYq*%4xwOKP*ivvnOQpBn9Q zv-9^``4LERx!Tfja>d5Lu(Y-;v;)JsT|zUaoLg8+ACwggibJLyBssnf62@xT##-w5 zYj4cH>vLzFm}m#m@py6O!!m2>v&T0LR+{M`USzQfK@Pi20-bc7FGeP zfK|Y4Gp+#!r6&vu(SomluYgtjXI9~Ao#-E_9NRH+$SVpePn*HevDV>^IQvNNs>UQi z^)MkeXS7eoi!y0{G*etVuZ0moy}h7X^LTp2L%g6&xt~d^vBkTH(9O82_j-4oeudY2 zjxtp`{=I<&xl z)s2AMz)f0k4;a%%l* zq5}xJ1g@{uSx(2N#`F3WH-^OyaAROG95BIR7+?d+;A42d2p_}L2b@1x8OO1}%2=KU zbQwB^*Iv*uEC~sL3FXh}cqo6CAxB6CAsH=5r|~Jo%9Ncn9SC9~h{?r@5nX1XT7>-( z_UA*j$j2y~IFTqrqKwb&A%n?6wMZ=^wakTTk@Lr93>uR|&L25{o=9SsjPigDa{kEq zBj>M6VqwD{c4AT`ft{E)_ZC^tZG`y!$-&2x2(b|5Dc$LD>)u2weMa|+zpd`U`eROG zcj&iY6AWzJ6^(jXNl#o(s|{n{Bh@iK(h{53j#eAH2wK9j5xcj6SCOo#pL4 zu7wJ#dy@`jn09Bx{J4*YUz2&Owo7=fX@zHEam7*&32TLKi7wF&i{gWVz>*T!2ke77 zZ6E`XK_gn=48TNSA~5l0R$iB1%kUffquaf;HxyzjQl3tYj@aKP4@PnkaY-JP<&wmS ze*eMp>F+Ogris;$Qj(O=P=xD? z$tW=~hDZPhU@t4M0B`^}=-36ofg&V`nWo(V4gd#$!&3T-od6sF4%dY|WCcY?W*7g; z9434-Z~DW$KFgdpRw%4xx-*hy3;MU8v3X+qVpyu^l-|y{;E` z-2T$@e}ulXSxEU8)0$oH)x2-a+*w)TbBo2IT?tC9vA$RHj~qUboN|v2=M>S*ZtO4l zYmA-lQuo3QwX7SJYSvR@sS!sTyFBg61v-?l^g5kUO=(T$p8021ns5i5a2zHaU|YDu z8me0GmF6rFHmpY$0?^{H7AVcTJh&yjwZIQ^P^vO55RU*^V@eLh1H=R3LBRtA6l}=DgP)k}!3_(0C@Chy*P!%jbfgm0S51^KymPoZMWr)C~!KJ~a z!KMGt`QfL|f@DIsb(%b+5 diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testPositiveViolationIsDistributedProportionallyAmongMixedChildrenWithArbitraryFloats@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testPositiveViolationIsDistributedProportionallyAmongMixedChildrenWithArbitraryFloats@3x.png deleted file mode 100644 index cb8efb682daa733cff234a79695053a35b1c4577..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32630 zcmeHPZA@EL7(VyXje?*BgD4+K*&s18l{pEEL}^(GFl3I8VA&jL)Tl5O6wMe+X)$7$ zX3-eQ#2>n$f)N;tV3bf(!pxS;u>}S*%oOLxCS%wI1meP0&pr2+-E#*1^Ur)p%DuGQ z^L6_^@AJIxxo^|fE!p9rF`Lfi#)rHxaq-!W{lKv4= zl~Ywd?mJKkHKg%Tbx9awG&sme4+Lm(-Fgf zKlXA2_YwV{`$CNNhO_Ad)5Ae?Y2u}ll;?@;{%NTx?ZkYq*%4xwOKP*ivvnOQpBn9Q zv-9^``4LERx!Tfja>d5Lu(Y-;v;)JsT|zUaoLg8+ACwggibJLyBssnf62@xT##-w5 zYj4cH>vLzFm}m#m@py6O!!m2>v&T0LR+{M`USzQfK@Pi20-bc7FGeP zfK|Y4Gp+#!r6&vu(SomluYgtjXI9~Ao#-E_9NRH+$SVpePn*HevDV>^IQvNNs>UQi z^)MkeXS7eoi!y0{G*etVuZ0moy}h7X^LTp2L%g6&xt~d^vBkTH(9O82_j-4oeudY2 zjxtp`{=I<&xl z)s2AMz)f0k4;a%%l* zq5}xJ1g@{uSx(2N#`F3WH-^OyaAROG95BIR7+?d+;A42d2p_}L2b@1x8OO1}%2=KU zbQwB^*Iv*uEC~sL3FXh}cqo6CAxB6CAsH=5r|~Jo%9Ncn9SC9~h{?r@5nX1XT7>-( z_UA*j$j2y~IFTqrqKwb&A%n?6wMZ=^wakTTk@Lr93>uR|&L25{o=9SsjPigDa{kEq zBj>M6VqwD{c4AT`ft{E)_ZC^tZG`y!$-&2x2(b|5Dc$LD>)u2weMa|+zpd`U`eROG zcj&iY6AWzJ6^(jXNl#o(s|{n{Bh@iK(h{53j#eAH2wK9j5xcj6SCOo#pL4 zu7wJ#dy@`jn09Bx{J4*YUz2&Owo7=fX@zHEam7*&32TLKi7wF&i{gWVz>*T!2ke77 zZ6E`XK_gn=48TNSA~5l0R$iB1%kUffquaf;HxyzjQl3tYj@aKP4@PnkaY-JP<&wmS ze*eMp>F+Ogris;$Qj(O=P=xD? z$tW=~hDZPhU@t4M0B`^}=-36ofg&V`nWo(V4gd#$!&3T-od6sF4%dY|WCcY?W*7g; z9434-Z~DW$KFgdpRw%4xx-*hy3;MU8v3X+qVpyu^l-|y{;E` z-2T$@e}ulXSxEU8)0$oH)x2-a+*w)TbBo2IT?tC9vA$RHj~qUboN|v2=M>S*ZtO4l zYmA-lQuo3QwX7SJYSvR@sS!sTyFBg61v-?l^g5kUO=(T$p8021ns5i5a2zHaU|YDu z8me0GmF6rFHmpY$0?^{H7AVcTJh&yjwZIQ^P^vO55RU*^V@eLh1H=R3LBRtA6l}=DgP)k}!3_(0C@Chy*P!%jbfgm0S51^KymPoZMWr)C~!KJ~a z!KMGt`QfL|f@DIsb(%b+5 diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testPositiveViolationIsDistributedProportionallyWithArbitraryFloats@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testPositiveViolationIsDistributedProportionallyWithArbitraryFloats@3x.png deleted file mode 100644 index 573dea9c820b38e907bb5b73127852a0f89b68e4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24670 zcmeHOUr19?96tM_O>=QAu~-8)A(tf+C*IMN?&|g^bSWm*|&-#kuCY{GrBpq_nHyp%iV{cIdc z3TCx<_c{kp%>@qj6sumGBMPNjBN)u>tdSb$2zF#vYYL?Lnb<2Cah>tCAIdlNRh!!S zV}8>a?-d&w*YJC=hGB!Cqy5G`CU;D~xqH_R@SI017|>TLHEL zjA?lE+(`ixGAIfc#@|lWk4+w`7#3GELo{l9$y9jXX|&s}KD=>z=Hixc#wZ+3T)UVr zH|p#0_s0CjvoVwhstqQQh^-$QZ#Eh7G+Il^or;WPS%1yGkh^#GXD;FI!x{taJ~sYM zQJ+=T?>ZUI8!bMi`7havHY+V|I=*?OZoNFUwMY|KG`Zp_RuLWnX~UO5U&QV6`FriM zdkA=OAdabm#mQ|(unMJ5@Hhex5BrFmRNFwSKxFZvCCFM<#|1r(jRZ#kTQ}@EvCD@& z5mk-wRsL&V8$e#sp zV6%iL1Bg*ZjIJL=_tamNJGywflr{2MRo?aVo7){N<+8yFrKRL!|3I6u@u=;ZE#|^y zR^I1Kp8wP0^B#M0_j}MFP5YU?w-5%9-jT4-}5}b z<|6m@G{aH@MNw%kr+qg?r3CT8&Os|vZpn&H^ugWRMXK{f)<^VDs>fM+kfO5l@IgDy zZmdF!SvB^;5_Hy~1O3oZ^eZQE#($d|R=h2c(AnX#3nlgR$Sc8+wUJ|l8L97eW4Fni zv+u~Fot9eXXnw3x7dMtQu^eynQM8U>xu?eV(c(x8nkaGRTHZAn~) z7yS=?eEU#aoc(#}p)pmx1s4o>R#ojmHqX%?-{J#*eCxW?50lOSi1o?B<6q z;5oI`n?2I>V}n`Uyp1zNn|(Fu>TY^7x!~!nF=MsVSC_5Xe4vPPGdpIxvJzaGa5K14 zjuwbY_<~~;{7YEb-jrS;EjcoiHa^SkUxx~2VU{Tv2!)F^0DK<9B|_G|u^c&qNuGcU zi95hOavH_t0fGX80+0gmQRVM|kARPm6(B1>R)DMkSpiC^L>~`o1*N431PKTd5F{W- zK#=||L5f`HkL)V#xjz}!j-To)Y}|>MwK?|Ty8h3>l0g&(;x{!@vKW@}(m{L*f~OSf`;^C4@CCDfjNpQ0io)K`P?9QdAkw z6=D}19$R)%;ag+^*}GgZ;<-h{Zri!|fNDv2+GoXx^4}nKmage1s}=DN(j9g1hvurf zBfFm1y?noUlMLDv)*R_OtcsD1Uq|d(H-vAi`YH0tZ&V}QE@D@GXzJun<*mspgR8LC z09*x8MTCFw1x(bGfK{kN2Cxnp5anzj3y4htS-@-xcoim|KtT~l2eyvO87OQ}7+i4!6BitP1=Fbuma| diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testRemainingViolationIsAppliedProperlyToFirstFlexibleChildWithArbitraryFloats@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testRemainingViolationIsAppliedProperlyToFirstFlexibleChildWithArbitraryFloats@3x.png deleted file mode 100644 index ee836d5cfb0e63dcf8c4e5d04f61535f781c5a2c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17877 zcmeHNZ%7ki7{8mhI=8GdS4LT#G0K8+eJN#-yKAcrYFhfm@GpH5f<`4O<=n=iOarOt z4+&*Ke+XnzAHt%oB~b)vD9nNwmXU#FnHrXMz3;o-pYVG@Ji>YU?w-5%9-jT4-}5}b z<|6m@G{aH@MNw%kr+qg?r3CT8&Os|vZpn&H^ugWRMXK{f)<^VDs>fM+kfO5l@IgDy zZmdF!SvB^;5_Hy~1O3oZ^eZQE#($d|R=h2c(AnX#3nlgR$Sc8+wUJ|l8L97eW4Fni zv+u~Fot9eXXnw3x7dMtQu^eynQM8U>xu?eV(c(x8nkaGRTHZAn~) z7yS=?eEU#aoc(#}p)pmx1s4o>R#ojmHqX%?-{J#*eCxW?50lOSi1o?B<6q z;5oI`n?2I>V}n`Uyp1zNn|(Fu>TY^7x!~!nF=MsVSC_5Xe4vPPGdpIxvJzaGa5K14 zjuwbY_<~~;{7YEb-jrS;EjcoiHa^SkUxx~2VU{Tv2!)F^0DK<9B|_G|u^c&qNuGcU zi95hOavH_t0fGX80+0gmQRVM|kARPm6(B1>R)DMkSpiC^L>~`o1*N431PKTd5F{W- zK#=||L5f`HkL)V#xjz}!j-To)Y}|>MwK?|Ty8h3>l0g&(;x{!@vKW@}(m{L*f~OSf`;^C4@CCDfjNpQ0io)K`P?9QdAkw z6=D}19$R)%;ag+^*}GgZ;<-h{Zri!|fNDv2+GoXx^4}nKmage1s}=DN(j9g1hvurf zBfFm1y?noUlMLDv)*R_OtcsD1Uq|d(H-vAi`YH0tZ&V}QE@D@GXzJun<*mspgR8LC z09*x8MTCFw1x(bGfK{kN2Cxnp5anzj3y4htS-@-xcoim|KtT~l2eyvO87OQ}7+i4!6BitP1=Fbuma| diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testStackSpacingWithChildrenHavingNilObjects_variableHeight@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testStackSpacingWithChildrenHavingNilObjects_variableHeight@3x.png deleted file mode 100644 index bb44b6a4df485340b9f06ad193dc3c39f0285fca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1130 zcmeAS@N?(olHy`uVBq!ia0y~yU~U1jZ8+F~q@8`qJ|M+d9OUlAuC_iL1_Xoj{pC!SrcdljQTgAsDC>e@xwof10&u? XlYvolLCQ^F0$}iT^>bP0l+XkK{X+er diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testStackSpacing_variableHeight@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testStackSpacing_variableHeight@3x.png deleted file mode 100644 index b5d3bc5e9a40fe61e7c3e7ebc6eada740c020a04..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10376 zcmeHNZ%kWN6u1`)l8?t*Oc~ZZRT+vZ|eqJqU3@gmfC-2%HysO7mgh+V)f_=)#YA zVfbKZalYDyki3IjT;<79H!$-KIb3^TWbP&XDSKU_X=SqM=;ocrJOlCawX309(ZE%&fW>LilPp(*zx93}H6=bm z9RDn@6yDfA_tcUXd7tNaL94~bubD)t&nzl(ZZIb7c#(rCnsQK&MP~*c5{>&i`MlGJ zlXDe$SSR4K8^{_<8E0~-s%RV%XF$vZUDJOW^%mG{_;@Xjz+Q*wn%ypSEJuTMp$*HmQWJ2^(5GOigA@=9?^pSVH=j^QJEr z&WF^_3xDuRzn@1~l&+b@;Gcf~WDaEDZIZTBgjAT&%*lt7E7meL^=}sNL_brK2STQA zbr~IlWm7fY=OnEQC*<3v@f+P=$+6iHRowF3rlU}ZNA-MAu@0sfv)F&_V}r$udW4e6w&~ALA(YJ% z2skp;ouw%Ji@kecct=cam(Do89;m>i6$!-Qspnm_gMCg z&XWn2M(qUssx$m3zP`H41@nBWJU#%wSO|D{L+1V~-Y}%)zRebGDF+cTBdUBjzAc3p z^;o>?(2_-qtbI`cWuYM;{^~*`xy% sMb==jR*m(OtTSiF2X+v9)K7~6-PQ(U(>b&0b@Eri>dG3&1;u^zFVja5>Hq)$ diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testUnderflowBehaviors_flex@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testUnderflowBehaviors_flex@3x.png deleted file mode 100644 index f5479576db79294b39f87a0a46c0b96bedd60129..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4251 zcmeAS@N?(olHy`uVBq!ia0y~yU~U1jr*W_W$+jJCW!A6Sf@q4AHvzaaTzTbP^&&X~OP;lV+spqqpWlmUpu(f9qa9H5vAfU&R zX!>ai^Zx=@W*&q-}nKfsp3|NnDa`ac1i1gxMY!Q0UW!D!=Sv{5zMFdc1hk9Jx{J7XiO dlL=}NtPVMM{Y{2?4X|av;OXk;vd$@?2>`u~+mQeO diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testUnderflowBehaviors_justifyCenter@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testUnderflowBehaviors_justifyCenter@3x.png deleted file mode 100644 index f89083148f977a11d412e4ef3571ac5358b449fa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4296 zcmeAS@N?(olHy`uVBq!ia0y~yU~U1jr*W_W$+jJCWYw9hWC~_H9m~UJF7Rjaq5u&)e#T1A2kH;n85-9%+&{E-|8>p|#ix_* zFkEX174ddrYHZMSXgCn&AdvTWuit^JP`#793BD1mi2}^~CJGv`atPeu;sEQ4SbIu! zC*vB<)e0glEKH2S4Il#*?)<8r+i-PN%p~apvo>%YQedl*S5Dv(P}m?U&=Ot0UU);) zRPQ3@2;neC4GvBgrezF_Owo*vJHCFmVq6`%Q^mZ&G*Pt0k>`h<+W`>;p#Ky&w*QM$ zPuQw8{R!I!wKYuv0zw=tK8#E(+nAaPUcWD83R_*|na7ZQNQ#j7GN`c@LK}A>zy1u6a=t)nJ4MMcS9VmZ<^qsfZfXyM;hKI z<8VEzVxt3gFB^0)-an4R^;~!(tba7ZU}o7ZDgW>=G zh3RX40$U2wpq9eh(RRXUJ7Kh)Fxs#iZHXiGBSu@|qg|(w+;y_^bTkV*Reo0l*j`}p MboFyt=akR{0Nvt2Bme*a diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testUnderflowBehaviors_justifyEnd@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testUnderflowBehaviors_justifyEnd@3x.png deleted file mode 100644 index 7c06d73fa3e4de608801420e9001735efe7f497a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4062 zcmeAS@N?(olHy`uVBq!ia0y~yU~U1jr*W_W$+jJCW~t@dzkI}H!u3lZBGBGEH;qn;U!8F2C&O=d{B32y-~ znrB8!v(cg%TctUH!vxHTcKzfy@i(^Oyr+b-|}wGK@)|#J*tQ8ljPQ3Yx?u^#~sc;e`@Uh8UEPDT+Xa2Xd(P#+p>3+zv^T^ zI3_qgc>b8b@x5@wj$h&VRrgMtuNKU7;b!k@-ozopsS{FqS-9egKTo5}gWtgiTv>eP zd{TDNzWA%(Tlvs~+k7JIse%?l$fg~r02-O_@KyZYmzDbW*SIYa)RocTJEc^hvLWEA zum6KUdqWnX#-kDi!i_2qA15|%;8?($>5Rp`10_I%6g+=a+)&VA%5c7Q;ZWnF1v*Ub zOx&S&zp%)C6?Rq-jObxB7xWOalQZM!X1F!MY)ioc3ytmr6Aw6rn%g$I|2-n$!Qvy% zBE~YQrN5o`kWz!$65dhgjE2r=+8NDRqvg(MsXSUqj8>te4Gj7;zy32aF#P{NzpO0* z*lJw?YPG%{ZL^NHSw~y+(EinEe`mBeINCWK?YfT+Y>W>3j1Gzojv>SUjGm5WfoA`T REP*4h44$rjF6*2UngGr|3itp3 diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testUnderflowBehaviors_justifySpaceBetween@3x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASStackLayoutSpecSnapshotTests/testUnderflowBehaviors_justifySpaceBetween@3x.png deleted file mode 100644 index eea9e51c30ad0076df75ea900e7166f098c38b05..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5521 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 R=mJ*P44$rjF6*2UngBMwy@mh) From 56d50e6d5e22aa12c4a47eec9f610ef5f5bf57d8 Mon Sep 17 00:00:00 2001 From: Michael Schneider Date: Tue, 18 Oct 2016 13:55:13 -0700 Subject: [PATCH 10/59] Add ASAbsoluteLayoutSpecSizing (#2394) Add ability for ASAbsoluteLayoutSpec to grow as far as possible or shrink to fit it's children --- AsyncDisplayKit/Layout/ASAbsoluteLayoutSpec.h | 23 +++++++++++-- .../Layout/ASAbsoluteLayoutSpec.mm | 33 +++++++++++++++---- 2 files changed, 47 insertions(+), 9 deletions(-) diff --git a/AsyncDisplayKit/Layout/ASAbsoluteLayoutSpec.h b/AsyncDisplayKit/Layout/ASAbsoluteLayoutSpec.h index a2b46d921b..5ed9467f47 100644 --- a/AsyncDisplayKit/Layout/ASAbsoluteLayoutSpec.h +++ b/AsyncDisplayKit/Layout/ASAbsoluteLayoutSpec.h @@ -10,15 +10,32 @@ #import +/** How much space the spec will take up. */ +typedef NS_ENUM(NSInteger, ASAbsoluteLayoutSpecSizing) { + /** The spec will take up the maximum size possible. */ + ASAbsoluteLayoutSpecSizingDefault, + /** Computes a size for the spec that is the union of all childrens' frames. */ + ASAbsoluteLayoutSpecSizingSizeToFit, +}; + NS_ASSUME_NONNULL_BEGIN /** - * A layout spec that positions children at fixed positions. - * - * Computes a size that is the union of all childrens' frames. + A layout spec that positions children at fixed positions. */ @interface ASAbsoluteLayoutSpec : ASLayoutSpec +/** + How much space will the spec taken up + */ +@property (nonatomic, assign) ASAbsoluteLayoutSpecSizing sizing; + +/** + @param sizing How much space the spec will take up + @param children Children to be positioned at fixed positions + */ ++ (instancetype)absoluteLayoutSpecWithSizing:(ASAbsoluteLayoutSpecSizing)sizing children:(NSArray> *)children AS_WARN_UNUSED_RESULT; + /** @param children Children to be positioned at fixed positions */ diff --git a/AsyncDisplayKit/Layout/ASAbsoluteLayoutSpec.mm b/AsyncDisplayKit/Layout/ASAbsoluteLayoutSpec.mm index 1fdb527d31..5e6377d66f 100644 --- a/AsyncDisplayKit/Layout/ASAbsoluteLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASAbsoluteLayoutSpec.mm @@ -14,33 +14,54 @@ #import "ASLayoutPrivate.h" #import "ASLayoutElementStylePrivate.h" + +#pragma mark - ASAbsoluteLayoutSpec + @implementation ASAbsoluteLayoutSpec +#pragma mark - Class + + (instancetype)absoluteLayoutSpecWithChildren:(NSArray *)children { return [[self alloc] initWithChildren:children]; } ++ (instancetype)absoluteLayoutSpecWithSizing:(ASAbsoluteLayoutSpecSizing)sizing children:(NSArray> *)children +{ + return [[self alloc] initWithSizing:sizing children:children]; +} + +#pragma mark - Lifecycle + - (instancetype)init { - return [self initWithChildren:@[]]; + return [self initWithChildren:nil]; } - (instancetype)initWithChildren:(NSArray *)children +{ + return [self initWithSizing:ASAbsoluteLayoutSpecSizingDefault children:children]; +} + +- (instancetype)initWithSizing:(ASAbsoluteLayoutSpecSizing)sizing children:(NSArray> *)children { if (!(self = [super init])) { return nil; } + + _sizing = sizing; self.children = children; + return self; } +#pragma mark - ASLayoutSpec + - (ASLayout *)calculateLayoutThatFits:(ASSizeRange)constrainedSize { - // TODO: layout: isValidForLayout() call should not be necessary if INFINITY is used CGSize size = { - (isinf(constrainedSize.max.width) || !ASPointsValidForLayout(constrainedSize.max.width)) ? ASLayoutElementParentDimensionUndefined : constrainedSize.max.width, - (isinf(constrainedSize.max.height) || !ASPointsValidForLayout(constrainedSize.max.height)) ? ASLayoutElementParentDimensionUndefined : constrainedSize.max.height + ASPointsValidForSize(constrainedSize.max.width) == NO ? ASLayoutElementParentDimensionUndefined : constrainedSize.max.width, + ASPointsValidForSize(constrainedSize.max.height) == NO ? ASLayoutElementParentDimensionUndefined : constrainedSize.max.height }; NSArray *children = self.children; @@ -60,14 +81,14 @@ [sublayouts addObject:sublayout]; } - if (isnan(size.width)) { + if (_sizing == ASAbsoluteLayoutSpecSizingSizeToFit || isnan(size.width)) { size.width = constrainedSize.min.width; for (ASLayout *sublayout in sublayouts) { size.width = MAX(size.width, sublayout.position.x + sublayout.size.width); } } - if (isnan(size.height)) { + if (_sizing == ASAbsoluteLayoutSpecSizingSizeToFit || isnan(size.height)) { size.height = constrainedSize.min.height; for (ASLayout *sublayout in sublayouts) { size.height = MAX(size.height, sublayout.position.y + sublayout.size.height); From abd80494c7ea5b0b470a8306fdc3089c40070fc1 Mon Sep 17 00:00:00 2001 From: Michael Schneider Date: Tue, 18 Oct 2016 15:55:55 -0700 Subject: [PATCH 11/59] [ASLayoutElementStyle] ASLayoutElementStyle improvements (#2413) * Use std::atomic for properties in ASLayoutElementStyle * Remove setter calls for min / max width and height in ASLayoutElementStyle --- AsyncDisplayKit/Layout/ASLayoutElement.mm | 119 +++++++++++----------- 1 file changed, 61 insertions(+), 58 deletions(-) diff --git a/AsyncDisplayKit/Layout/ASLayoutElement.mm b/AsyncDisplayKit/Layout/ASLayoutElement.mm index 087ec1af57..a0761324b1 100644 --- a/AsyncDisplayKit/Layout/ASLayoutElement.mm +++ b/AsyncDisplayKit/Layout/ASLayoutElement.mm @@ -13,6 +13,7 @@ #import "ASDisplayNodeInternal.h" #import +#import CGFloat const ASLayoutElementParentDimensionUndefined = NAN; CGSize const ASLayoutElementParentSizeUndefined = {ASLayoutElementParentDimensionUndefined, ASLayoutElementParentDimensionUndefined}; @@ -110,21 +111,21 @@ do {\ @implementation ASLayoutElementStyle { ASDN::RecursiveMutex __instanceLock__; ASLayoutElementSize _size; + + std::atomic _spacingBefore; + std::atomic _spacingAfter; + std::atomic _flexGrow; + std::atomic _flexShrink; + std::atomic _flexBasis; + std::atomic _alignSelf; + std::atomic _ascender; + std::atomic _descender; + std::atomic _layoutPosition; } @dynamic width, height, minWidth, maxWidth, minHeight, maxHeight; @dynamic preferredSize, minSize, maxSize, preferredLayoutSize, minLayoutSize, maxLayoutSize; -@synthesize spacingBefore = _spacingBefore; -@synthesize spacingAfter = _spacingAfter; -@synthesize flexGrow = _flexGrow; -@synthesize flexShrink = _flexShrink; -@synthesize flexBasis = _flexBasis; -@synthesize alignSelf = _alignSelf; -@synthesize ascender = _ascender; -@synthesize descender = _descender; -@synthesize layoutPosition = _layoutPosition; - #pragma mark - Lifecycle - (instancetype)initWithDelegate:(id)delegate @@ -242,22 +243,33 @@ do {\ #pragma mark - ASLayoutElementStyleSizeHelpers +// We explicitly not call the setter for (max/min) width and height to avoid locking overhead + - (void)setPreferredSize:(CGSize)preferredSize { - self.width = ASDimensionMakeWithPoints(preferredSize.width); - self.height = ASDimensionMakeWithPoints(preferredSize.height); + ASDN::MutexLocker l(__instanceLock__); + _size.width = ASDimensionMakeWithPoints(preferredSize.width); + _size.height = ASDimensionMakeWithPoints(preferredSize.height); + ASLayoutElementStyleCallDelegate(ASLayoutElementStyleWidthProperty); + ASLayoutElementStyleCallDelegate(ASLayoutElementStyleHeightProperty); } - (void)setMinSize:(CGSize)minSize { - self.minWidth = ASDimensionMakeWithPoints(minSize.width); - self.minHeight = ASDimensionMakeWithPoints(minSize.height); + ASDN::MutexLocker l(__instanceLock__); + _size.minWidth = ASDimensionMakeWithPoints(minSize.width); + _size.minHeight = ASDimensionMakeWithPoints(minSize.height); + ASLayoutElementStyleCallDelegate(ASLayoutElementStyleMinWidthProperty); + ASLayoutElementStyleCallDelegate(ASLayoutElementStyleMinHeightProperty); } - (void)setMaxSize:(CGSize)maxSize { - self.maxWidth = ASDimensionMakeWithPoints(maxSize.width); - self.maxHeight = ASDimensionMakeWithPoints(maxSize.height); + ASDN::MutexLocker l(__instanceLock__); + _size.maxWidth = ASDimensionMakeWithPoints(maxSize.width); + _size.maxHeight = ASDimensionMakeWithPoints(maxSize.height); + ASLayoutElementStyleCallDelegate(ASLayoutElementStyleMaxWidthProperty); + ASLayoutElementStyleCallDelegate(ASLayoutElementStyleMaxHeightProperty); } - (ASLayoutSize)preferredLayoutSize @@ -268,8 +280,11 @@ do {\ - (void)setPreferredLayoutSize:(ASLayoutSize)preferredLayoutSize { - self.width = preferredLayoutSize.width; - self.height = preferredLayoutSize.height; + ASDN::MutexLocker l(__instanceLock__); + _size.width = preferredLayoutSize.width; + _size.height = preferredLayoutSize.height; + ASLayoutElementStyleCallDelegate(ASLayoutElementStyleWidthProperty); + ASLayoutElementStyleCallDelegate(ASLayoutElementStyleHeightProperty); } - (ASLayoutSize)minLayoutSize @@ -280,8 +295,11 @@ do {\ - (void)setMinLayoutSize:(ASLayoutSize)minLayoutSize { - self.minWidth = minLayoutSize.width; - self.minHeight = minLayoutSize.height; + ASDN::MutexLocker l(__instanceLock__); + _size.minWidth = minLayoutSize.width; + _size.minHeight = minLayoutSize.height; + ASLayoutElementStyleCallDelegate(ASLayoutElementStyleMinWidthProperty); + ASLayoutElementStyleCallDelegate(ASLayoutElementStyleMinHeightProperty); } - (ASLayoutSize)maxLayoutSize @@ -292,8 +310,11 @@ do {\ - (void)setMaxLayoutSize:(ASLayoutSize)maxLayoutSize { - self.maxWidth = maxLayoutSize.width; - self.maxHeight = maxLayoutSize.height; + ASDN::MutexLocker l(__instanceLock__); + _size.maxWidth = maxLayoutSize.width; + _size.maxHeight = maxLayoutSize.height; + ASLayoutElementStyleCallDelegate(ASLayoutElementStyleMaxWidthProperty); + ASLayoutElementStyleCallDelegate(ASLayoutElementStyleMaxHeightProperty); } @@ -301,121 +322,103 @@ do {\ - (void)setSpacingBefore:(CGFloat)spacingBefore { - ASDN::MutexLocker l(__instanceLock__); - _spacingBefore = spacingBefore; + _spacingBefore.store(spacingBefore); ASLayoutElementStyleCallDelegate(ASLayoutElementStyleSpacingBeforeProperty); } - (CGFloat)spacingBefore { - ASDN::MutexLocker l(__instanceLock__); - return _spacingBefore; + return _spacingBefore.load(); } - (void)setSpacingAfter:(CGFloat)spacingAfter { - ASDN::MutexLocker l(__instanceLock__); - _spacingAfter = spacingAfter; + _spacingAfter.store(spacingAfter); ASLayoutElementStyleCallDelegate(ASLayoutElementStyleSpacingAfterProperty); } - (CGFloat)spacingAfter { - ASDN::MutexLocker l(__instanceLock__); - return _spacingAfter; + return _spacingAfter.load(); } - (void)setFlexGrow:(CGFloat)flexGrow { - ASDN::MutexLocker l(__instanceLock__); - _flexGrow = flexGrow; + _flexGrow.store(flexGrow); ASLayoutElementStyleCallDelegate(ASLayoutElementStyleFlexGrowProperty); } - (CGFloat)flexGrow { - ASDN::MutexLocker l(__instanceLock__); - return _flexGrow; + return _flexGrow.load(); } - (void)setFlexShrink:(CGFloat)flexShrink { - ASDN::MutexLocker l(__instanceLock__); - _flexShrink = flexShrink; + _flexShrink.store(flexShrink); ASLayoutElementStyleCallDelegate(ASLayoutElementStyleFlexShrinkProperty); } - (CGFloat)flexShrink { - ASDN::MutexLocker l(__instanceLock__); - return _flexShrink; + return _flexShrink.load(); } - (void)setFlexBasis:(ASDimension)flexBasis { - ASDN::MutexLocker l(__instanceLock__); - _flexBasis = flexBasis; + _flexBasis.store(flexBasis); ASLayoutElementStyleCallDelegate(ASLayoutElementStyleFlexBasisProperty); } - (ASDimension)flexBasis { - ASDN::MutexLocker l(__instanceLock__); - return _flexBasis; + return _flexBasis.load(); } - (void)setAlignSelf:(ASStackLayoutAlignSelf)alignSelf { - ASDN::MutexLocker l(__instanceLock__); - _alignSelf = alignSelf; + _alignSelf.store(alignSelf); ASLayoutElementStyleCallDelegate(ASLayoutElementStyleAlignSelfProperty); } - (ASStackLayoutAlignSelf)alignSelf { - ASDN::MutexLocker l(__instanceLock__); - return _alignSelf; + return _alignSelf.load(); } - (void)setAscender:(CGFloat)ascender { - ASDN::MutexLocker l(__instanceLock__); - _ascender = ascender; + _ascender.store(ascender); ASLayoutElementStyleCallDelegate(ASLayoutElementStyleAscenderProperty); } - (CGFloat)ascender { - ASDN::MutexLocker l(__instanceLock__); - return _ascender; + return _ascender.load(); } - (void)setDescender:(CGFloat)descender { - ASDN::MutexLocker l(__instanceLock__); - _descender = descender; + _descender.store(descender); ASLayoutElementStyleCallDelegate(ASLayoutElementStyleDescenderProperty); } - (CGFloat)descender { - ASDN::MutexLocker l(__instanceLock__); - return _descender; + return _descender.load(); } #pragma mark - ASAbsoluteLayoutElement - (void)setLayoutPosition:(CGPoint)layoutPosition { - ASDN::MutexLocker l(__instanceLock__); - _layoutPosition = layoutPosition; + _layoutPosition.store(layoutPosition); ASLayoutElementStyleCallDelegate(ASLayoutElementStyleLayoutPositionProperty); } - (CGPoint)layoutPosition { - ASDN::MutexLocker l(__instanceLock__); - return _layoutPosition; + return _layoutPosition.load(); } @end From d32bf3f297be141f84fe5ad6553e966d949526eb Mon Sep 17 00:00:00 2001 From: Adlai Holler Date: Wed, 19 Oct 2016 10:45:58 -0700 Subject: [PATCH 12/59] Conditionally import signpost header to fix Xcode 7 build (#2432) --- AsyncDisplayKit/Details/ASDataController.mm | 2 -- AsyncDisplayKit/Details/ASRangeController.mm | 2 -- Base/ASLog.h | 7 +++++-- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/AsyncDisplayKit/Details/ASDataController.mm b/AsyncDisplayKit/Details/ASDataController.mm index 16f2ab87b0..7638a4e1d4 100644 --- a/AsyncDisplayKit/Details/ASDataController.mm +++ b/AsyncDisplayKit/Details/ASDataController.mm @@ -23,8 +23,6 @@ #import "ASInternalHelpers.h" #import "ASCellNode+Internal.h" -#import - //#define LOG(...) NSLog(__VA_ARGS__) #define LOG(...) diff --git a/AsyncDisplayKit/Details/ASRangeController.mm b/AsyncDisplayKit/Details/ASRangeController.mm index ab4dfc7e3e..2da5de760a 100644 --- a/AsyncDisplayKit/Details/ASRangeController.mm +++ b/AsyncDisplayKit/Details/ASRangeController.mm @@ -22,8 +22,6 @@ #import "ASDisplayNode+FrameworkPrivate.h" #import "AsyncDisplayKit+Debug.h" -#import - #define AS_RANGECONTROLLER_LOG_UPDATE_FREQ 0 @interface ASRangeController () diff --git a/Base/ASLog.h b/Base/ASLog.h index 8f0d1e3cfe..9e4a7bebaf 100644 --- a/Base/ASLog.h +++ b/Base/ASLog.h @@ -10,7 +10,6 @@ #pragma once -#import #import "ASAvailability.h" #define ASMultiplexImageNodeLogDebug(...) @@ -19,7 +18,11 @@ #define ASMultiplexImageNodeLogError(...) #define ASMultiplexImageNodeCLogError(...) -#if PROFILE +// Note: `` only exists in Xcode 8 and later. +#if PROFILE && __has_include("") + +#import + // These definitions are required to build the backward-compatible kdebug trace // on the iOS 10 SDK. The kdebug_trace function crashes if run on iOS 9 and earlier. // It's valuable to support trace signposts on iOS 9, because A5 devices don't support iOS 10. From 67489492ee0380ab28dcefda24420bc350ed071d Mon Sep 17 00:00:00 2001 From: Adlai Holler Date: Wed, 19 Oct 2016 11:49:49 -0700 Subject: [PATCH 13/59] Fix Uncalled Collection Delegate Methods (#2433) * Fix batch fetching * Fix not calling constrainedSizeForItemAtIndexPath: * Fix constrainedSizeForItemAtIndexPath: not being called --- AsyncDisplayKit/ASCollectionView.mm | 6 +++++- .../Details/ASCollectionViewFlowLayoutInspector.m | 7 +++++-- .../ASCollectionViewFlowLayoutInspectorTests.m | 11 ++++++----- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/AsyncDisplayKit/ASCollectionView.mm b/AsyncDisplayKit/ASCollectionView.mm index ded30340ea..27079d1441 100644 --- a/AsyncDisplayKit/ASCollectionView.mm +++ b/AsyncDisplayKit/ASCollectionView.mm @@ -1224,7 +1224,11 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell"; - (void)_beginBatchFetching { [_batchContext beginBatchFetching]; - if (_asyncDelegateFlags.collectionViewWillBeginBatchFetch) { + if (_asyncDelegateFlags.collectionNodeWillBeginBatchFetch) { + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + [_asyncDelegate collectionNode:self.collectionNode willBeginBatchFetchWithContext:_batchContext]; + }); + } else if (_asyncDelegateFlags.collectionViewWillBeginBatchFetch) { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" diff --git a/AsyncDisplayKit/Details/ASCollectionViewFlowLayoutInspector.m b/AsyncDisplayKit/Details/ASCollectionViewFlowLayoutInspector.m index ef9b35a7ca..d82aa45a58 100644 --- a/AsyncDisplayKit/Details/ASCollectionViewFlowLayoutInspector.m +++ b/AsyncDisplayKit/Details/ASCollectionViewFlowLayoutInspector.m @@ -34,6 +34,7 @@ static inline ASSizeRange NodeConstrainedSizeForScrollDirection(ASCollectionView @implementation ASCollectionViewLayoutInspector { struct { + unsigned int implementsConstrainedSizeForNodeAtIndexPathDeprecated:1; unsigned int implementsConstrainedSizeForNodeAtIndexPath:1; } _delegateFlags; } @@ -56,14 +57,16 @@ static inline ASSizeRange NodeConstrainedSizeForScrollDirection(ASCollectionView if (delegate == nil) { memset(&_delegateFlags, 0, sizeof(_delegateFlags)); } else { - _delegateFlags.implementsConstrainedSizeForNodeAtIndexPath = [delegate respondsToSelector:@selector(collectionView:constrainedSizeForNodeAtIndexPath:)]; + _delegateFlags.implementsConstrainedSizeForNodeAtIndexPathDeprecated = [delegate respondsToSelector:@selector(collectionView:constrainedSizeForNodeAtIndexPath:)]; + _delegateFlags.implementsConstrainedSizeForNodeAtIndexPath = [delegate respondsToSelector:@selector(collectionNode:constrainedSizeForItemAtIndexPath:)]; } } - (ASSizeRange)collectionView:(ASCollectionView *)collectionView constrainedSizeForNodeAtIndexPath:(NSIndexPath *)indexPath { if (_delegateFlags.implementsConstrainedSizeForNodeAtIndexPath) { - // TODO: Handle collection node + return [collectionView.asyncDelegate collectionNode:collectionView.collectionNode constrainedSizeForItemAtIndexPath:indexPath]; + } else if (_delegateFlags.implementsConstrainedSizeForNodeAtIndexPathDeprecated) { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" return [collectionView.asyncDelegate collectionView:collectionView constrainedSizeForNodeAtIndexPath:indexPath]; diff --git a/AsyncDisplayKitTests/ASCollectionViewFlowLayoutInspectorTests.m b/AsyncDisplayKitTests/ASCollectionViewFlowLayoutInspectorTests.m index f4c7e229a1..22b2768d6d 100644 --- a/AsyncDisplayKitTests/ASCollectionViewFlowLayoutInspectorTests.m +++ b/AsyncDisplayKitTests/ASCollectionViewFlowLayoutInspectorTests.m @@ -377,24 +377,25 @@ - (void)testThatItThrowsIfNodeConstrainedSizeIsImplementedOnDataSourceButNotOnDelegateLayoutInspector { UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init]; - ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout]; + ASCollectionNode *node = [[ASCollectionNode alloc] initWithCollectionViewLayout:layout]; + ASCollectionView *collectionView = node.view; id dataSourceAndDelegate = [OCMockObject mockForProtocol:@protocol(InspectorTestDataSourceDelegateProtocol)]; ASSizeRange constrainedSize = ASSizeRangeMake(CGSizeZero, CGSizeZero); NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:0]; NSValue *value = [NSValue value:&constrainedSize withObjCType:@encode(ASSizeRange)]; - [[[dataSourceAndDelegate stub] andReturnValue:value] collectionView:collectionView constrainedSizeForNodeAtIndexPath:indexPath]; - collectionView.asyncDataSource = dataSourceAndDelegate; + [[[dataSourceAndDelegate stub] andReturnValue:value] collectionNode:node constrainedSizeForItemAtIndexPath:indexPath]; + node.dataSource = dataSourceAndDelegate; id delegate = [InspectorTestDataSourceDelegateWithoutNodeConstrainedSize new]; - collectionView.asyncDelegate = delegate; + node.delegate = delegate; ASCollectionViewLayoutInspector *inspector = [[ASCollectionViewLayoutInspector alloc] initWithCollectionView:collectionView]; collectionView.layoutInspector = inspector; XCTAssertThrows([inspector collectionView:collectionView constrainedSizeForNodeAtIndexPath:indexPath]); - collectionView.asyncDelegate = dataSourceAndDelegate; + node.delegate = dataSourceAndDelegate; XCTAssertNoThrow([inspector collectionView:collectionView constrainedSizeForNodeAtIndexPath:indexPath]); } From 4b914f8e15b547f62d4e50f023cd6617df18bbbf Mon Sep 17 00:00:00 2001 From: Michael Schneider Date: Wed, 19 Oct 2016 12:55:19 -0700 Subject: [PATCH 14/59] Add preferredSize as getter to ASLayoutElementStyle (#2427) --- AsyncDisplayKit/Layout/ASLayoutElement.h | 5 +++-- AsyncDisplayKit/Layout/ASLayoutElement.mm | 16 ++++++++++++++++ AsyncDisplayKitTests/ASLayoutElementStyleTests.m | 16 +++++++++++++++- 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/AsyncDisplayKit/Layout/ASLayoutElement.h b/AsyncDisplayKit/Layout/ASLayoutElement.h index e933ee36e3..b55aeb0c2c 100644 --- a/AsyncDisplayKit/Layout/ASLayoutElement.h +++ b/AsyncDisplayKit/Layout/ASLayoutElement.h @@ -250,10 +250,11 @@ extern NSString * const ASLayoutElementStyleLayoutPositionProperty; * @discussion This method is optional, but one of either preferredSize or preferredLayoutSize is required * for nodes that either have no intrinsic content size or * should be laid out at a different size than its intrinsic content size. For example, this property could be - * set on an ASImageNode to display at a size different from the underlying image size. + * set on an ASImageNode to display at a size different from the underlying image size. + * + * @warning Calling the getter when the size's width or height are relative will cause an assert. */ @property (nonatomic, assign) CGSize preferredSize; -- (CGSize)preferredSize UNAVAILABLE_ATTRIBUTE; /** * @abstract An optional property that provides a minimum size bound for a layout element. If provided, this restriction will diff --git a/AsyncDisplayKit/Layout/ASLayoutElement.mm b/AsyncDisplayKit/Layout/ASLayoutElement.mm index a0761324b1..2f563124da 100644 --- a/AsyncDisplayKit/Layout/ASLayoutElement.mm +++ b/AsyncDisplayKit/Layout/ASLayoutElement.mm @@ -254,6 +254,22 @@ do {\ ASLayoutElementStyleCallDelegate(ASLayoutElementStyleHeightProperty); } +- (CGSize)preferredSize +{ + ASDN::MutexLocker l(__instanceLock__); + if (_size.width.unit != ASDimensionUnitPoints) { + NSCAssert(NO, @"Cannot get preferredSize of element with fractional width. Width: %@.", NSStringFromASDimension(_size.width)); + return CGSizeZero; + } + + if (_size.height.unit != ASDimensionUnitPoints) { + NSCAssert(NO, @"Cannot get preferredSize of element with fractional height. Height: %@.", NSStringFromASDimension(_size.height)); + return CGSizeZero; + } + + return CGSizeMake(_size.width.value, _size.height.value); +} + - (void)setMinSize:(CGSize)minSize { ASDN::MutexLocker l(__instanceLock__); diff --git a/AsyncDisplayKitTests/ASLayoutElementStyleTests.m b/AsyncDisplayKitTests/ASLayoutElementStyleTests.m index 6f4caabebb..e2551f6cfd 100644 --- a/AsyncDisplayKitTests/ASLayoutElementStyleTests.m +++ b/AsyncDisplayKitTests/ASLayoutElementStyleTests.m @@ -8,7 +8,7 @@ // of patent rights can be found in the PATENTS file in the same directory. // -#import +#import "ASXCTExtensions.h" #import "ASLayoutElement.h" #pragma mark - ASLayoutElementStyleTestsDelegate @@ -61,6 +61,7 @@ CGSize size = CGSizeMake(100, 100); style.preferredSize = size; + ASXCTAssertEqualSizes(style.preferredSize, size); XCTAssertTrue(ASDimensionEqualToDimension(style.width, ASDimensionMakeWithPoints(size.width))); XCTAssertTrue(ASDimensionEqualToDimension(style.height, ASDimensionMakeWithPoints(size.height))); @@ -73,6 +74,19 @@ XCTAssertTrue(ASDimensionEqualToDimension(style.maxHeight, ASDimensionMakeWithPoints(size.height))); } +- (void)testReadingInvalidSizeForPreferredSize +{ + ASLayoutElementStyle *style = [ASLayoutElementStyle new]; + + XCTAssertThrows(style.preferredSize); + + style.width = ASDimensionMake(ASDimensionUnitFraction, 0.5); + XCTAssertThrows(style.preferredSize); + + style.preferredSize = CGSizeMake(100, 100); + XCTAssertNoThrow(style.preferredSize); +} + - (void)testSettingSizeViaLayoutSize { ASLayoutElementStyle *style = [ASLayoutElementStyle new]; From 84d1a637d7e474ed9beccc3e50fdb8305d970021 Mon Sep 17 00:00:00 2001 From: Hannah Troisi Date: Wed, 19 Oct 2016 14:48:06 -0700 Subject: [PATCH 15/59] [2.0] add helpful deprecation messages (#2437) [2.0] add helpful deprecation messages --- AsyncDisplayKit/ASCollectionNode+Beta.h | 6 +- AsyncDisplayKit/ASCollectionNode.h | 31 ++++++---- AsyncDisplayKit/ASCollectionNode.mm | 5 ++ AsyncDisplayKit/ASCollectionView.h | 56 +++++++++---------- AsyncDisplayKit/ASCollectionViewProtocols.h | 30 +++++----- AsyncDisplayKit/ASDisplayNode+Deprecated.h | 20 +++---- AsyncDisplayKit/ASDisplayNode.h | 2 +- AsyncDisplayKit/ASTableNode.h | 27 +++++---- AsyncDisplayKit/ASTableNode.mm | 5 ++ AsyncDisplayKit/ASTableView.h | 54 +++++++++--------- AsyncDisplayKit/ASTableViewProtocols.h | 24 ++++---- AsyncDisplayKit/ASTextNode.h | 6 +- .../ASCollectionViewFlowLayoutInspector.h | 2 +- AsyncDisplayKit/Details/ASIndexPath.m | 2 +- AsyncDisplayKit/Layout/ASDimension.h | 2 +- AsyncDisplayKit/Layout/ASLayoutElement.h | 4 +- AsyncDisplayKit/Layout/ASLayoutSpec.h | 2 +- AsyncDisplayKit/Layout/ASLayoutSpec.mm | 2 +- AsyncDisplayKit/Private/_AS-objc-internal.h | 2 +- Base/ASBaseDefines.h | 8 +-- 20 files changed, 156 insertions(+), 134 deletions(-) diff --git a/AsyncDisplayKit/ASCollectionNode+Beta.h b/AsyncDisplayKit/ASCollectionNode+Beta.h index cc2860099b..d1476c0baf 100644 --- a/AsyncDisplayKit/ASCollectionNode+Beta.h +++ b/AsyncDisplayKit/ASCollectionNode+Beta.h @@ -17,11 +17,11 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout layoutFacilitator:(nullable id)layoutFacilitator; -- (void)beginUpdates ASDISPLAYNODE_DEPRECATED; +- (void)beginUpdates ASDISPLAYNODE_DEPRECATED_MSG("Use -performBatchUpdates:completion: instead."); -- (void)endUpdatesAnimated:(BOOL)animated ASDISPLAYNODE_DEPRECATED; +- (void)endUpdatesAnimated:(BOOL)animated ASDISPLAYNODE_DEPRECATED_MSG("Use -performBatchUpdates:completion: instead."); -- (void)endUpdatesAnimated:(BOOL)animated completion:(nullable void (^)(BOOL))completion ASDISPLAYNODE_DEPRECATED; +- (void)endUpdatesAnimated:(BOOL)animated completion:(nullable void (^)(BOOL))completion ASDISPLAYNODE_DEPRECATED_MSG("Use -performBatchUpdates:completion: instead."); @end diff --git a/AsyncDisplayKit/ASCollectionNode.h b/AsyncDisplayKit/ASCollectionNode.h index 932c6de132..ab4c06ce03 100644 --- a/AsyncDisplayKit/ASCollectionNode.h +++ b/AsyncDisplayKit/ASCollectionNode.h @@ -265,6 +265,13 @@ NS_ASSUME_NONNULL_BEGIN */ - (void)reloadData; +/** + * Triggers a relayout of all nodes. + * + * @discussion This method invalidates and lays out every cell node in the collection view. + */ +- (void)relayoutItems; + #pragma mark - Querying Data /** @@ -333,7 +340,7 @@ NS_ASSUME_NONNULL_BEGIN * @deprecated This method is deprecated in 2.0. Use @c reloadDataWithCompletion: and * then @c waitUntilAllUpdatesAreCommitted instead. */ -- (void)reloadDataImmediately ASDISPLAYNODE_DEPRECATED; +- (void)reloadDataImmediately ASDISPLAYNODE_DEPRECATED_MSG("Use -reloadDataWithCompletion: followed by -waitUntilAllUpdatesAreCommitted instead."); @end @@ -415,7 +422,7 @@ NS_ASSUME_NONNULL_BEGIN * not implement reuse (it will be called once per row). Unlike UICollectionView's version, * this method is not called when the row is about to display. */ -- (ASCellNode *)collectionView:(ASCollectionView *)collectionView nodeForItemAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED; +- (ASCellNode *)collectionView:(ASCollectionView *)collectionView nodeForItemAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED_MSG("Use ASCollectionNode's method instead."); /** * Similar to -collectionView:nodeForItemAtIndexPath: @@ -429,7 +436,7 @@ NS_ASSUME_NONNULL_BEGIN * Must be thread-safe (can be called on the main thread or a background * queue) and should not implement reuse (it will be called once per row). */ -- (ASCellNodeBlock)collectionView:(ASCollectionView *)collectionView nodeBlockForItemAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED; +- (ASCellNodeBlock)collectionView:(ASCollectionView *)collectionView nodeBlockForItemAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED_MSG("Use ASCollectionNode's method instead."); /** * Asks the collection view to provide a supplementary node to display in the collection view. @@ -438,7 +445,7 @@ NS_ASSUME_NONNULL_BEGIN * @param kind The kind of supplementary node to provide. * @param indexPath The index path that specifies the location of the new supplementary node. */ -- (ASCellNode *)collectionView:(ASCollectionView *)collectionView nodeForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED; +- (ASCellNode *)collectionView:(ASCollectionView *)collectionView nodeForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED_MSG("Use ASCollectionNode's method instead."); /** * Indicator to lock the data source for data fetching in async mode. @@ -448,7 +455,7 @@ NS_ASSUME_NONNULL_BEGIN * @param collectionView The sender. * @deprecated The data source is always accessed on the main thread, and this method will not be called. */ -- (void)collectionViewLockDataSource:(ASCollectionView *)collectionView ASDISPLAYNODE_DEPRECATED; +- (void)collectionViewLockDataSource:(ASCollectionView *)collectionView ASDISPLAYNODE_DEPRECATED_MSG("Data source accesses are on the main thread. Method will not be called."); /** * Indicator to unlock the data source for data fetching in async mode. @@ -458,7 +465,7 @@ NS_ASSUME_NONNULL_BEGIN * @param collectionView The sender. * @deprecated The data source is always accessed on the main thread, and this method will not be called. */ -- (void)collectionViewUnlockDataSource:(ASCollectionView *)collectionView ASDISPLAYNODE_DEPRECATED; +- (void)collectionViewUnlockDataSource:(ASCollectionView *)collectionView ASDISPLAYNODE_DEPRECATED_MSG("Data source accesses are on the main thread. Method will not be called."); @end @@ -536,7 +543,7 @@ NS_ASSUME_NONNULL_BEGIN * * @return A constrained size range for layout the node at this index path. */ -- (ASSizeRange)collectionView:(ASCollectionView *)collectionView constrainedSizeForNodeAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED; +- (ASSizeRange)collectionView:(ASCollectionView *)collectionView constrainedSizeForNodeAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED_MSG("Use ASCollectionNode's method instead."); /** * Informs the delegate that the collection view will add the given node @@ -550,7 +557,7 @@ NS_ASSUME_NONNULL_BEGIN * passed into this method may not correspond to the same item in your data source * if your data source has been updated since the last edit was processed. */ -- (void)collectionView:(ASCollectionView *)collectionView willDisplayNode:(ASCellNode *)node forItemAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED; +- (void)collectionView:(ASCollectionView *)collectionView willDisplayNode:(ASCellNode *)node forItemAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED_MSG("Use ASCollectionNode's method instead."); /** * Informs the delegate that the collection view did remove the provided node from the view hierarchy. @@ -565,9 +572,9 @@ NS_ASSUME_NONNULL_BEGIN * passed into this method may not correspond to the same item in your data source * if your data source has been updated since the last edit was processed. */ -- (void)collectionView:(ASCollectionView *)collectionView didEndDisplayingNode:(ASCellNode *)node forItemAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED; +- (void)collectionView:(ASCollectionView *)collectionView didEndDisplayingNode:(ASCellNode *)node forItemAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED_MSG("Use ASCollectionNode's method instead."); -- (void)collectionView:(ASCollectionView *)collectionView willBeginBatchFetchWithContext:(ASBatchContext *)context ASDISPLAYNODE_DEPRECATED; +- (void)collectionView:(ASCollectionView *)collectionView willBeginBatchFetchWithContext:(ASBatchContext *)context ASDISPLAYNODE_DEPRECATED_MSG("Use ASCollectionNode's method instead."); /** * Tell the collectionView if batch fetching should begin. @@ -580,7 +587,7 @@ NS_ASSUME_NONNULL_BEGIN * If not implemented, the collectionView assumes that it should notify its asyncDelegate when batch fetching * should occur. */ -- (BOOL)shouldBatchFetchForCollectionView:(ASCollectionView *)collectionView ASDISPLAYNODE_DEPRECATED; +- (BOOL)shouldBatchFetchForCollectionView:(ASCollectionView *)collectionView ASDISPLAYNODE_DEPRECATED_MSG("Use ASCollectionNode's method instead."); /** * Informs the delegate that the collection view will add the node @@ -595,7 +602,7 @@ NS_ASSUME_NONNULL_BEGIN * * This method is deprecated. Use @c collectionView:willDisplayNode:forItemAtIndexPath: instead. */ -- (void)collectionView:(ASCollectionView *)collectionView willDisplayNodeForItemAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED; +- (void)collectionView:(ASCollectionView *)collectionView willDisplayNodeForItemAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED_MSG("Use ASCollectionNode's method instead."); @end diff --git a/AsyncDisplayKit/ASCollectionNode.mm b/AsyncDisplayKit/ASCollectionNode.mm index 111691b824..07d2c8c5a4 100644 --- a/AsyncDisplayKit/ASCollectionNode.mm +++ b/AsyncDisplayKit/ASCollectionNode.mm @@ -338,6 +338,11 @@ [self.view reloadData]; } +- (void)relayoutItems +{ + [self.view relayoutItems]; +} + - (void)reloadDataImmediately { [self.view reloadDataImmediately]; diff --git a/AsyncDisplayKit/ASCollectionView.h b/AsyncDisplayKit/ASCollectionView.h index bb0da3c704..35f1307a1a 100644 --- a/AsyncDisplayKit/ASCollectionView.h +++ b/AsyncDisplayKit/ASCollectionView.h @@ -145,7 +145,7 @@ NS_ASSUME_NONNULL_BEGIN * * @param layout The layout object to use for organizing items. The collection view stores a strong reference to the specified object. Must not be nil. */ -- (instancetype)initWithCollectionViewLayout:(UICollectionViewLayout *)layout ASDISPLAYNODE_DEPRECATED; +- (instancetype)initWithCollectionViewLayout:(UICollectionViewLayout *)layout ASDISPLAYNODE_DEPRECATED_MSG("Please use ASCollectionNode instead of ASCollectionView."); /** * Initializes an ASCollectionView @@ -155,7 +155,7 @@ NS_ASSUME_NONNULL_BEGIN * @param frame The frame rectangle for the collection view, measured in points. The origin of the frame is relative to the superview in which you plan to add it. This frame is passed to the superclass during initialization. * @param layout The layout object to use for organizing items. The collection view stores a strong reference to the specified object. Must not be nil. */ -- (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout ASDISPLAYNODE_DEPRECATED; +- (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout ASDISPLAYNODE_DEPRECATED_MSG("Please use ASCollectionNode instead of ASCollectionView."); /** * Tuning parameters for a range type in full mode. @@ -167,7 +167,7 @@ NS_ASSUME_NONNULL_BEGIN * @see ASLayoutRangeMode * @see ASLayoutRangeType */ -- (ASRangeTuningParameters)tuningParametersForRangeType:(ASLayoutRangeType)rangeType AS_WARN_UNUSED_RESULT ASDISPLAYNODE_DEPRECATED; +- (ASRangeTuningParameters)tuningParametersForRangeType:(ASLayoutRangeType)rangeType AS_WARN_UNUSED_RESULT ASDISPLAYNODE_DEPRECATED_MSG("Use ASCollectionNode method instead."); /** * Set the tuning parameters for a range type in full mode. @@ -178,7 +178,7 @@ NS_ASSUME_NONNULL_BEGIN * @see ASLayoutRangeMode * @see ASLayoutRangeType */ -- (void)setTuningParameters:(ASRangeTuningParameters)tuningParameters forRangeType:(ASLayoutRangeType)rangeType ASDISPLAYNODE_DEPRECATED; +- (void)setTuningParameters:(ASRangeTuningParameters)tuningParameters forRangeType:(ASLayoutRangeType)rangeType ASDISPLAYNODE_DEPRECATED_MSG("Use ASCollectionNode method instead."); /** * Tuning parameters for a range type in the specified mode. @@ -191,7 +191,7 @@ NS_ASSUME_NONNULL_BEGIN * @see ASLayoutRangeMode * @see ASLayoutRangeType */ -- (ASRangeTuningParameters)tuningParametersForRangeMode:(ASLayoutRangeMode)rangeMode rangeType:(ASLayoutRangeType)rangeType AS_WARN_UNUSED_RESULT ASDISPLAYNODE_DEPRECATED; +- (ASRangeTuningParameters)tuningParametersForRangeMode:(ASLayoutRangeMode)rangeMode rangeType:(ASLayoutRangeType)rangeType AS_WARN_UNUSED_RESULT ASDISPLAYNODE_DEPRECATED_MSG("Use ASCollectionNode method instead."); /** * Set the tuning parameters for a range type in the specified mode. @@ -203,7 +203,7 @@ NS_ASSUME_NONNULL_BEGIN * @see ASLayoutRangeMode * @see ASLayoutRangeType */ -- (void)setTuningParameters:(ASRangeTuningParameters)tuningParameters forRangeMode:(ASLayoutRangeMode)rangeMode rangeType:(ASLayoutRangeType)rangeType ASDISPLAYNODE_DEPRECATED; +- (void)setTuningParameters:(ASRangeTuningParameters)tuningParameters forRangeMode:(ASLayoutRangeMode)rangeMode rangeType:(ASLayoutRangeType)rangeType ASDISPLAYNODE_DEPRECATED_MSG("Use ASCollectionNode method instead."); /** * Perform a batch of updates asynchronously, optionally disabling all animations in the batch. This method must be called from the main thread. @@ -215,7 +215,7 @@ NS_ASSUME_NONNULL_BEGIN * Boolean parameter that contains the value YES if all of the related animations completed successfully or * NO if they were interrupted. This parameter may be nil. If supplied, the block is run on the main thread. */ -- (void)performBatchAnimated:(BOOL)animated updates:(nullable __attribute((noescape)) void (^)())updates completion:(nullable void (^)(BOOL finished))completion ASDISPLAYNODE_DEPRECATED; +- (void)performBatchAnimated:(BOOL)animated updates:(nullable __attribute((noescape)) void (^)())updates completion:(nullable void (^)(BOOL finished))completion ASDISPLAYNODE_DEPRECATED_MSG("Use ASCollectionNode method instead."); /** * Perform a batch of updates asynchronously. This method must be called from the main thread. @@ -226,7 +226,7 @@ NS_ASSUME_NONNULL_BEGIN * Boolean parameter that contains the value YES if all of the related animations completed successfully or * NO if they were interrupted. This parameter may be nil. If supplied, the block is run on the main thread. */ -- (void)performBatchUpdates:(nullable __attribute((noescape)) void (^)())updates completion:(nullable void (^)(BOOL finished))completion ASDISPLAYNODE_DEPRECATED; +- (void)performBatchUpdates:(nullable __attribute((noescape)) void (^)())updates completion:(nullable void (^)(BOOL finished))completion ASDISPLAYNODE_DEPRECATED_MSG("Use ASCollectionNode method instead."); /** * Reload everything from scratch, destroying the working range and all cached nodes. @@ -235,14 +235,14 @@ NS_ASSUME_NONNULL_BEGIN * the main thread. * @warning This method is substantially more expensive than UICollectionView's version. */ -- (void)reloadDataWithCompletion:(nullable void (^)())completion ASDISPLAYNODE_DEPRECATED; +- (void)reloadDataWithCompletion:(nullable void (^)())completion ASDISPLAYNODE_DEPRECATED_MSG("Use ASCollectionNode method instead."); /** * Reload everything from scratch, destroying the working range and all cached nodes. * * @warning This method is substantially more expensive than UICollectionView's version. */ -- (void)reloadData ASDISPLAYNODE_DEPRECATED; +- (void)reloadData ASDISPLAYNODE_DEPRECATED_MSG("Use ASCollectionNode method instead."); /** * Reload everything from scratch entirely on the main thread, destroying the working range and all cached nodes. @@ -250,19 +250,19 @@ NS_ASSUME_NONNULL_BEGIN * @warning This method is substantially more expensive than UICollectionView's version and will block the main thread * while all the cells load. */ -- (void)reloadDataImmediately ASDISPLAYNODE_DEPRECATED; +- (void)reloadDataImmediately ASDISPLAYNODE_DEPRECATED_MSG("Use ASCollectionNode's -reloadDataWithCompletion: followed by -waitUntilAllUpdatesAreCommitted instead."); /** * Triggers a relayout of all nodes. * * @discussion This method invalidates and lays out every cell node in the collection. */ -- (void)relayoutItems ASDISPLAYNODE_DEPRECATED; +- (void)relayoutItems ASDISPLAYNODE_DEPRECATED_MSG("Use ASCollectionNode method instead."); /** * Blocks execution of the main thread until all section and row updates are committed. This method must be called from the main thread. */ -- (void)waitUntilAllUpdatesAreCommitted ASDISPLAYNODE_DEPRECATED; +- (void)waitUntilAllUpdatesAreCommitted ASDISPLAYNODE_DEPRECATED_MSG("Use ASCollectionNode method instead."); /** * Registers the given kind of supplementary node for use in creating node-backed supplementary views. @@ -274,7 +274,7 @@ NS_ASSUME_NONNULL_BEGIN * methods. This method will register an internal backing view that will host the contents of the supplementary nodes * returned from the data source. */ -- (void)registerSupplementaryNodeOfKind:(NSString *)elementKind ASDISPLAYNODE_DEPRECATED; +- (void)registerSupplementaryNodeOfKind:(NSString *)elementKind ASDISPLAYNODE_DEPRECATED_MSG("Use ASCollectionNode method instead."); /** * Inserts one or more sections. @@ -284,7 +284,7 @@ NS_ASSUME_NONNULL_BEGIN * @discussion This method must be called from the main thread. The asyncDataSource must be updated to reflect the changes * before this method is called. */ -- (void)insertSections:(NSIndexSet *)sections ASDISPLAYNODE_DEPRECATED; +- (void)insertSections:(NSIndexSet *)sections ASDISPLAYNODE_DEPRECATED_MSG("Use ASCollectionNode method instead."); /** * Deletes one or more sections. @@ -294,7 +294,7 @@ NS_ASSUME_NONNULL_BEGIN * @discussion This method must be called from the main thread. The asyncDataSource must be updated to reflect the changes * before this method is called. */ -- (void)deleteSections:(NSIndexSet *)sections ASDISPLAYNODE_DEPRECATED; +- (void)deleteSections:(NSIndexSet *)sections ASDISPLAYNODE_DEPRECATED_MSG("Use ASCollectionNode method instead."); /** * Reloads the specified sections. @@ -304,7 +304,7 @@ NS_ASSUME_NONNULL_BEGIN * @discussion This method must be called from the main thread. The asyncDataSource must be updated to reflect the changes * before this method is called. */ -- (void)reloadSections:(NSIndexSet *)sections ASDISPLAYNODE_DEPRECATED; +- (void)reloadSections:(NSIndexSet *)sections ASDISPLAYNODE_DEPRECATED_MSG("Use ASCollectionNode method instead."); /** * Moves a section to a new location. @@ -316,7 +316,7 @@ NS_ASSUME_NONNULL_BEGIN * @discussion This method must be called from the main thread. The asyncDataSource must be updated to reflect the changes * before this method is called. */ -- (void)moveSection:(NSInteger)section toSection:(NSInteger)newSection ASDISPLAYNODE_DEPRECATED; +- (void)moveSection:(NSInteger)section toSection:(NSInteger)newSection ASDISPLAYNODE_DEPRECATED_MSG("Use ASCollectionNode method instead."); /** * Inserts items at the locations identified by an array of index paths. @@ -326,7 +326,7 @@ NS_ASSUME_NONNULL_BEGIN * @discussion This method must be called from the main thread. The asyncDataSource must be updated to reflect the changes * before this method is called. */ -- (void)insertItemsAtIndexPaths:(NSArray *)indexPaths ASDISPLAYNODE_DEPRECATED; +- (void)insertItemsAtIndexPaths:(NSArray *)indexPaths ASDISPLAYNODE_DEPRECATED_MSG("Use ASCollectionNode method instead."); /** * Deletes the items specified by an array of index paths. @@ -336,7 +336,7 @@ NS_ASSUME_NONNULL_BEGIN * @discussion This method must be called from the main thread. The asyncDataSource must be updated to reflect the changes * before this method is called. */ -- (void)deleteItemsAtIndexPaths:(NSArray *)indexPaths ASDISPLAYNODE_DEPRECATED; +- (void)deleteItemsAtIndexPaths:(NSArray *)indexPaths ASDISPLAYNODE_DEPRECATED_MSG("Use ASCollectionNode method instead."); /** * Reloads the specified items. @@ -346,7 +346,7 @@ NS_ASSUME_NONNULL_BEGIN * @discussion This method must be called from the main thread. The asyncDataSource must be updated to reflect the changes * before this method is called. */ -- (void)reloadItemsAtIndexPaths:(NSArray *)indexPaths ASDISPLAYNODE_DEPRECATED; +- (void)reloadItemsAtIndexPaths:(NSArray *)indexPaths ASDISPLAYNODE_DEPRECATED_MSG("Use ASCollectionNode method instead."); /** * Moves the item at a specified location to a destination location. @@ -358,7 +358,7 @@ NS_ASSUME_NONNULL_BEGIN * @discussion This method must be called from the main thread. The asyncDataSource must be updated to reflect the changes * before this method is called. */ -- (void)moveItemAtIndexPath:(NSIndexPath *)indexPath toIndexPath:(NSIndexPath *)newIndexPath ASDISPLAYNODE_DEPRECATED; +- (void)moveItemAtIndexPath:(NSIndexPath *)indexPath toIndexPath:(NSIndexPath *)newIndexPath ASDISPLAYNODE_DEPRECATED_MSG("Use ASCollectionNode method instead."); /** * Query the sized node at @c indexPath for its calculatedSize. @@ -367,14 +367,14 @@ NS_ASSUME_NONNULL_BEGIN * * This method is deprecated. Call @c calculatedSize on the node of interest instead. First deprecated in version 2.0. */ -- (CGSize)calculatedSizeForNodeAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED; +- (CGSize)calculatedSizeForNodeAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED_MSG("Call -calculatedSize on the node of interest instead."); /** * Similar to -visibleCells. * * @return an array containing the nodes being displayed on screen. */ -- (NSArray<__kindof ASCellNode *> *)visibleNodes AS_WARN_UNUSED_RESULT ASDISPLAYNODE_DEPRECATED; +- (NSArray<__kindof ASCellNode *> *)visibleNodes AS_WARN_UNUSED_RESULT ASDISPLAYNODE_DEPRECATED_MSG("Use ASCollectionNode method instead."); /** * Similar to -indexPathForCell:. @@ -388,15 +388,15 @@ NS_ASSUME_NONNULL_BEGIN * for use with your data source and @c ASCollectionNode, call @c indexPathForNode: on the * collection node instead. */ -- (nullable NSIndexPath *)indexPathForNode:(ASCellNode *)cellNode AS_WARN_UNUSED_RESULT ASDISPLAYNODE_DEPRECATED; +- (nullable NSIndexPath *)indexPathForNode:(ASCellNode *)cellNode AS_WARN_UNUSED_RESULT ASDISPLAYNODE_DEPRECATED_MSG("Use ASCollectionNode method instead."); @end -ASDISPLAYNODE_DEPRECATED +ASDISPLAYNODE_DEPRECATED_MSG("Renamed to ASCollectionDataSource.") @protocol ASCollectionViewDataSource @end -ASDISPLAYNODE_DEPRECATED +ASDISPLAYNODE_DEPRECATED_MSG("Renamed to ASCollectionDelegate.") @protocol ASCollectionViewDelegate @end @@ -416,7 +416,7 @@ ASDISPLAYNODE_DEPRECATED * `constrainedSizeForNodeAtIndexPath` * please file a github issue if you would like this to be restored. */ -- (UIEdgeInsets)collectionView:(ASCollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section __deprecated_msg("This method does nothing for 1.9.7+ due to incorrect implementation previously, see the header file for more information."); +- (UIEdgeInsets)collectionView:(ASCollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section ASDISPLAYNODE_DEPRECATED_MSG("This method does nothing for 1.9.7+ due to incorrect implementation previously, see the header file for more information."); /** * Asks the delegate for the size of the header in the specified section. diff --git a/AsyncDisplayKit/ASCollectionViewProtocols.h b/AsyncDisplayKit/ASCollectionViewProtocols.h index f071887284..793d697744 100644 --- a/AsyncDisplayKit/ASCollectionViewProtocols.h +++ b/AsyncDisplayKit/ASCollectionViewProtocols.h @@ -19,11 +19,11 @@ NS_ASSUME_NONNULL_BEGIN @optional -- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section ASDISPLAYNODE_DEPRECATED; +- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section ASDISPLAYNODE_DEPRECATED_MSG("Implement -collectionNode:numberOfItemsInSection: instead."); -- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView ASDISPLAYNODE_DEPRECATED; +- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView ASDISPLAYNODE_DEPRECATED_MSG("Implement -numberOfSectionsInCollectionNode: instead."); -- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED; +- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED_MSG("Implement - collectionNode:viewForSupplementaryElementOfKind:atIndexPath: instead."); @end @@ -39,21 +39,21 @@ NS_ASSUME_NONNULL_BEGIN - (UICollectionViewTransitionLayout *)collectionView:(UICollectionView *)collectionView transitionLayoutForOldLayout:(UICollectionViewLayout *)fromLayout newLayout:(UICollectionViewLayout *)toLayout; -- (void)collectionView:(UICollectionView *)collectionView willDisplaySupplementaryView:(UICollectionReusableView *)view forElementKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED; -- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingSupplementaryView:(UICollectionReusableView *)view forElementOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED; +- (void)collectionView:(UICollectionView *)collectionView willDisplaySupplementaryView:(UICollectionReusableView *)view forElementKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED_MSG("Implement -collectionNode:willDisplaySupplementaryView:forElementKind:atIndexPath: instead."); +- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingSupplementaryView:(UICollectionReusableView *)view forElementOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED_MSG("Implement -collectionNode:didEndDisplayingSupplementaryView:forElementKind:atIndexPath: instead."); -- (BOOL)collectionView:(UICollectionView *)collectionView shouldHighlightItemAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED; -- (void)collectionView:(UICollectionView *)collectionView didHighlightItemAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED; -- (void)collectionView:(UICollectionView *)collectionView didUnhighlightItemAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED; +- (BOOL)collectionView:(UICollectionView *)collectionView shouldHighlightItemAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED_MSG("Implement collectionNode:shouldHighlightItemAtIndexPath: instead."); +- (void)collectionView:(UICollectionView *)collectionView didHighlightItemAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED_MSG("Implement collectionNode:didHighlightItemAtIndexPath: instead."); +- (void)collectionView:(UICollectionView *)collectionView didUnhighlightItemAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED_MSG("Implement collectionNode:didUnhighlightItemAtIndexPath: instead."); -- (BOOL)collectionView:(UICollectionView *)collectionView shouldSelectItemAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED; -- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED; -- (BOOL)collectionView:(UICollectionView *)collectionView shouldDeselectItemAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED; -- (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED; +- (BOOL)collectionView:(UICollectionView *)collectionView shouldSelectItemAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED_MSG("Implement collectionNode:shouldSelectItemAtIndexPath: instead."); +- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED_MSG("Implement collectionNode:didSelectItemAtIndexPath: instead."); +- (BOOL)collectionView:(UICollectionView *)collectionView shouldDeselectItemAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED_MSG("Implement collectionNode:shouldDeselectItemAtIndexPath: instead."); +- (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED_MSG("Implement collectionNode:didDeselectItemAtIndexPath: instead."); -- (BOOL)collectionView:(UICollectionView *)collectionView shouldShowMenuForItemAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED; -- (BOOL)collectionView:(UICollectionView *)collectionView canPerformAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(nullable id)sender ASDISPLAYNODE_DEPRECATED; -- (void)collectionView:(UICollectionView *)collectionView performAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(nullable id)sender ASDISPLAYNODE_DEPRECATED; +- (BOOL)collectionView:(UICollectionView *)collectionView shouldShowMenuForItemAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED_MSG("Implement collectionNode:shouldShowMenuForItemAtIndexPath: instead."); +- (BOOL)collectionView:(UICollectionView *)collectionView canPerformAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(nullable id)sender ASDISPLAYNODE_DEPRECATED_MSG("Implement collectionNode:canPerformAction:forItemAtIndexPath:withSender: instead."); +- (void)collectionView:(UICollectionView *)collectionView performAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(nullable id)sender ASDISPLAYNODE_DEPRECATED_MSG("Implement collectionNode:performAction:forItemAtIndexPath:withSender: instead."); @end diff --git a/AsyncDisplayKit/ASDisplayNode+Deprecated.h b/AsyncDisplayKit/ASDisplayNode+Deprecated.h index e62dd4769b..2ec26b7b2b 100644 --- a/AsyncDisplayKit/ASDisplayNode+Deprecated.h +++ b/AsyncDisplayKit/ASDisplayNode+Deprecated.h @@ -33,7 +33,7 @@ * * @deprecated Deprecated in version 2.0: Use layoutThatFits: with a constrained size of (CGSizeZero, constrainedSize) and call size on the returned ASLayout */ -- (CGSize)measure:(CGSize)constrainedSize ASDISPLAYNODE_DEPRECATED; +- (CGSize)measure:(CGSize)constrainedSize ASDISPLAYNODE_DEPRECATED_MSG("Use layoutThatFits: with a constrained size of (CGSizeZero, constrainedSize) and call size on the returned ASLayout."); /** * @abstract Calculate a layout based on given size range. @@ -42,9 +42,9 @@ * * @return An ASLayout instance defining the layout of the receiver and its children. * - * @deprecated Deprecated in version 2.0: Use ASCalculateRootLayout or ASCalculateLayout instead + * @deprecated Deprecated in version 2.0: Use ASCalculateRootLayout() or ASCalculateLayout() instead */ -- (ASLayout *)measureWithSizeRange:(ASSizeRange)constrainedSize ASDISPLAYNODE_DEPRECATED; +- (ASLayout *)measureWithSizeRange:(ASSizeRange)constrainedSize ASDISPLAYNODE_DEPRECATED_MSG("Use layoutThatFits: instead."); /** * @abstract Called whenever the visiblity of the node changed. @@ -53,16 +53,16 @@ * * @deprecated @see didEnterVisibleState @see didExitVisibleState */ -- (void)visibilityDidChange:(BOOL)isVisible ASDISPLAYNODE_REQUIRES_SUPER ASDISPLAYNODE_DEPRECATED; +- (void)visibilityDidChange:(BOOL)isVisible ASDISPLAYNODE_REQUIRES_SUPER ASDISPLAYNODE_DEPRECATED_MSG("Use -didEnterVisibleState / -didExitVisibleState instead."); /** * @abstract Called whenever the visiblity of the node changed. * * @discussion Subclasses may use this to monitor when they become visible. * - * @deprecated @see didEnterVisibleState @see didExitVisibleStat + * @deprecated @see didEnterVisibleState @see didExitVisibleState */ -- (void)visibleStateDidChange:(BOOL)isVisible ASDISPLAYNODE_REQUIRES_SUPER ASDISPLAYNODE_DEPRECATED; +- (void)visibleStateDidChange:(BOOL)isVisible ASDISPLAYNODE_REQUIRES_SUPER ASDISPLAYNODE_DEPRECATED_MSG("Use -didEnterVisibleState / -didExitVisibleState instead."); /** * @abstract Called whenever the the node has entered or exited the display state. @@ -73,7 +73,7 @@ * * @deprecated @see didEnterDisplayState @see didExitDisplayState */ -- (void)displayStateDidChange:(BOOL)inDisplayState ASDISPLAYNODE_REQUIRES_SUPER ASDISPLAYNODE_DEPRECATED; +- (void)displayStateDidChange:(BOOL)inDisplayState ASDISPLAYNODE_REQUIRES_SUPER ASDISPLAYNODE_DEPRECATED_MSG("Use -didEnterDisplayState / -didExitDisplayState instead."); /** * @abstract Called whenever the the node has entered or left the load state. @@ -84,14 +84,14 @@ * * @deprecated @see didEnterPreloadState @see didExitPreloadState */ -- (void)loadStateDidChange:(BOOL)inLoadState ASDISPLAYNODE_REQUIRES_SUPER ASDISPLAYNODE_DEPRECATED; +- (void)loadStateDidChange:(BOOL)inLoadState ASDISPLAYNODE_REQUIRES_SUPER ASDISPLAYNODE_DEPRECATED_MSG("Use -didEnterPreloadState / -didExitPreloadState instead."); /** * @abstract Cancels all performing layout transitions. Can be called on any thread. * * @deprecated Deprecated in version 2.0: Use cancelLayoutTransition */ -- (void)cancelLayoutTransitionsInProgress ASDISPLAYNODE_DEPRECATED; +- (void)cancelLayoutTransitionsInProgress ASDISPLAYNODE_DEPRECATED_MSG("Use -cancelLayoutTransition instead."); /** * @abstract A boolean that shows whether the node automatically inserts and removes nodes based on the presence or @@ -102,6 +102,6 @@ * * @deprecated Deprecated in version 2.0: Use automaticallyManagesSubnodes */ -@property (nonatomic, assign) BOOL usesImplicitHierarchyManagement ASDISPLAYNODE_DEPRECATED; +@property (nonatomic, assign) BOOL usesImplicitHierarchyManagement ASDISPLAYNODE_DEPRECATED_MSG("Set .automaticallyManagesSubnodes instead."); @end diff --git a/AsyncDisplayKit/ASDisplayNode.h b/AsyncDisplayKit/ASDisplayNode.h index 565eec34a6..1c65546d89 100644 --- a/AsyncDisplayKit/ASDisplayNode.h +++ b/AsyncDisplayKit/ASDisplayNode.h @@ -832,7 +832,7 @@ extern NSInteger const ASDefaultDrawingPriority; * * @deprecated Deprecated in version 2.0: Just calls through to set the height and width property of the node. Convert to use sizing properties instead: height, minHeight, maxHeight, width, minWidth, maxWidth. */ -@property (nonatomic, assign, readwrite) CGSize preferredFrameSize ASDISPLAYNODE_DEPRECATED; +@property (nonatomic, assign, readwrite) CGSize preferredFrameSize ASDISPLAYNODE_DEPRECATED_MSG("Use .style.preferredSize instead OR set individual values with .style.height and .style.width."); @end diff --git a/AsyncDisplayKit/ASTableNode.h b/AsyncDisplayKit/ASTableNode.h index e1ed605855..854c1136f6 100644 --- a/AsyncDisplayKit/ASTableNode.h +++ b/AsyncDisplayKit/ASTableNode.h @@ -99,6 +99,13 @@ NS_ASSUME_NONNULL_BEGIN */ - (void)reloadData; +/** + * Triggers a relayout of all nodes. + * + * @discussion This method invalidates and lays out every cell node in the table view. + */ +- (void)relayoutItems; + /** * Perform a batch of updates asynchronously, optionally disabling all animations in the batch. This method must be called from the main thread. * The data source must be updated to reflect the changes before the update block completes. @@ -316,7 +323,7 @@ NS_ASSUME_NONNULL_BEGIN * @return a node for display at this indexpath. This will be called on the main thread and should not implement reuse (it will be called once per row). Unlike UITableView's version, this method * is not called when the row is about to display. */ -- (ASCellNode *)tableView:(ASTableView *)tableView nodeForRowAtIndexPath:(NSIndexPath *)indexPath AS_WARN_UNUSED_RESULT ASDISPLAYNODE_DEPRECATED; +- (ASCellNode *)tableView:(ASTableView *)tableView nodeForRowAtIndexPath:(NSIndexPath *)indexPath AS_WARN_UNUSED_RESULT ASDISPLAYNODE_DEPRECATED_MSG("Use ASTableNode's method instead."); /** * Similar to -tableView:nodeForRowAtIndexPath: @@ -329,7 +336,7 @@ NS_ASSUME_NONNULL_BEGIN * Must be thread-safe (can be called on the main thread or a background * queue) and should not implement reuse (it will be called once per row). */ -- (ASCellNodeBlock)tableView:(ASTableView *)tableView nodeBlockForRowAtIndexPath:(NSIndexPath *)indexPath AS_WARN_UNUSED_RESULT ASDISPLAYNODE_DEPRECATED; +- (ASCellNodeBlock)tableView:(ASTableView *)tableView nodeBlockForRowAtIndexPath:(NSIndexPath *)indexPath AS_WARN_UNUSED_RESULT ASDISPLAYNODE_DEPRECATED_MSG("Use ASTableNode's method instead."); /** * Indicator to lock the data source for data fetching in async mode. @@ -339,7 +346,7 @@ NS_ASSUME_NONNULL_BEGIN * @param tableView The sender. * @deprecated The data source is always accessed on the main thread, and this method will not be called. */ -- (void)tableViewLockDataSource:(ASTableView *)tableView ASDISPLAYNODE_DEPRECATED; +- (void)tableViewLockDataSource:(ASTableView *)tableView ASDISPLAYNODE_DEPRECATED_MSG("Data source accesses are on the main thread. Method will not be called."); /** * Indicator to unlock the data source for data fetching in asyn mode. @@ -349,7 +356,7 @@ NS_ASSUME_NONNULL_BEGIN * @param tableView The sender. * @deprecated The data source is always accessed on the main thread, and this method will not be called. */ -- (void)tableViewUnlockDataSource:(ASTableView *)tableView ASDISPLAYNODE_DEPRECATED; +- (void)tableViewUnlockDataSource:(ASTableView *)tableView ASDISPLAYNODE_DEPRECATED_MSG("Data source accesses are on the main thread. Method will not be called."); @end @@ -434,7 +441,7 @@ NS_ASSUME_NONNULL_BEGIN * passed into this method may not correspond to the same item in your data source * if your data source has been updated since the last edit was processed. */ -- (void)tableView:(ASTableView *)tableView willDisplayNode:(ASCellNode *)node forRowAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED; +- (void)tableView:(ASTableView *)tableView willDisplayNode:(ASCellNode *)node forRowAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED_MSG("Use ASTableNode's method instead."); /** * Informs the delegate that the table view did remove the provided node from the view hierarchy. @@ -449,7 +456,7 @@ NS_ASSUME_NONNULL_BEGIN * passed into this method may not correspond to the same item in your data source * if your data source has been updated since the last edit was processed. */ -- (void)tableView:(ASTableView *)tableView didEndDisplayingNode:(ASCellNode *)node forRowAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED; +- (void)tableView:(ASTableView *)tableView didEndDisplayingNode:(ASCellNode *)node forRowAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED_MSG("Use ASTableNode's method instead."); /** * Receive a message that the tableView is near the end of its data set and more data should be fetched if necessary. @@ -463,7 +470,7 @@ NS_ASSUME_NONNULL_BEGIN * ASTableView currently only supports batch events for tail loads. If you require a head load, consider implementing a * UIRefreshControl. */ -- (void)tableView:(ASTableView *)tableView willBeginBatchFetchWithContext:(ASBatchContext *)context ASDISPLAYNODE_DEPRECATED; +- (void)tableView:(ASTableView *)tableView willBeginBatchFetchWithContext:(ASBatchContext *)context ASDISPLAYNODE_DEPRECATED_MSG("Use ASTableNode's method instead."); /** * Tell the tableView if batch fetching should begin. @@ -476,7 +483,7 @@ NS_ASSUME_NONNULL_BEGIN * If not implemented, the tableView assumes that it should notify its asyncDelegate when batch fetching * should occur. */ -- (BOOL)shouldBatchFetchForTableView:(ASTableView *)tableView AS_WARN_UNUSED_RESULT ASDISPLAYNODE_DEPRECATED; +- (BOOL)shouldBatchFetchForTableView:(ASTableView *)tableView AS_WARN_UNUSED_RESULT ASDISPLAYNODE_DEPRECATED_MSG("Use ASTableNode's method instead."); /** * Provides the constrained size range for measuring the row at the index path. @@ -488,7 +495,7 @@ NS_ASSUME_NONNULL_BEGIN * * @return A constrained size range for layout the node at this index path. */ -- (ASSizeRange)tableView:(ASTableView *)tableView constrainedSizeForRowAtIndexPath:(NSIndexPath *)indexPath AS_WARN_UNUSED_RESULT ASDISPLAYNODE_DEPRECATED; +- (ASSizeRange)tableView:(ASTableView *)tableView constrainedSizeForRowAtIndexPath:(NSIndexPath *)indexPath AS_WARN_UNUSED_RESULT ASDISPLAYNODE_DEPRECATED_MSG("Use ASTableNode's method instead."); /** * Informs the delegate that the table view will add the node @@ -503,7 +510,7 @@ NS_ASSUME_NONNULL_BEGIN * * This method is deprecated. Use @c tableView:willDisplayNode:forRowAtIndexPath: instead. */ -- (void)tableView:(ASTableView *)tableView willDisplayNodeForRowAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED; +- (void)tableView:(ASTableView *)tableView willDisplayNodeForRowAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED_MSG("Use ASTableNode's method instead."); @end diff --git a/AsyncDisplayKit/ASTableNode.mm b/AsyncDisplayKit/ASTableNode.mm index d676775795..dc5daa0dae 100644 --- a/AsyncDisplayKit/ASTableNode.mm +++ b/AsyncDisplayKit/ASTableNode.mm @@ -287,6 +287,11 @@ ASEnvironmentCollectionTableSetEnvironmentState(_environmentStateLock) [self reloadDataWithCompletion:nil]; } +- (void)relayoutItems +{ + [self.view relayoutItems]; +} + - (void)performBatchAnimated:(BOOL)animated updates:(void (^)())updates completion:(void (^)(BOOL))completion { [self.view beginUpdates]; diff --git a/AsyncDisplayKit/ASTableView.h b/AsyncDisplayKit/ASTableView.h index 8876409753..301e94378b 100644 --- a/AsyncDisplayKit/ASTableView.h +++ b/AsyncDisplayKit/ASTableView.h @@ -74,7 +74,7 @@ NS_ASSUME_NONNULL_BEGIN * * @param style A constant that specifies the style of the table view. See UITableViewStyle for descriptions of valid constants. */ -- (instancetype)initWithFrame:(CGRect)frame style:(UITableViewStyle)style ASDISPLAYNODE_DEPRECATED; +- (instancetype)initWithFrame:(CGRect)frame style:(UITableViewStyle)style ASDISPLAYNODE_DEPRECATED_MSG("Please use ASTableNode instead of ASTableView."); /** * Tuning parameters for a range type in full mode. @@ -86,7 +86,7 @@ NS_ASSUME_NONNULL_BEGIN * @see ASLayoutRangeMode * @see ASLayoutRangeType */ -- (ASRangeTuningParameters)tuningParametersForRangeType:(ASLayoutRangeType)rangeType AS_WARN_UNUSED_RESULT ASDISPLAYNODE_DEPRECATED; +- (ASRangeTuningParameters)tuningParametersForRangeType:(ASLayoutRangeType)rangeType AS_WARN_UNUSED_RESULT ASDISPLAYNODE_DEPRECATED_MSG("Use ASTableNode method instead."); /** * Set the tuning parameters for a range type in full mode. @@ -97,7 +97,7 @@ NS_ASSUME_NONNULL_BEGIN * @see ASLayoutRangeMode * @see ASLayoutRangeType */ -- (void)setTuningParameters:(ASRangeTuningParameters)tuningParameters forRangeType:(ASLayoutRangeType)rangeType ASDISPLAYNODE_DEPRECATED; +- (void)setTuningParameters:(ASRangeTuningParameters)tuningParameters forRangeType:(ASLayoutRangeType)rangeType ASDISPLAYNODE_DEPRECATED_MSG("Use ASTableNode method instead."); /** * Tuning parameters for a range type in the specified mode. @@ -110,7 +110,7 @@ NS_ASSUME_NONNULL_BEGIN * @see ASLayoutRangeMode * @see ASLayoutRangeType */ -- (ASRangeTuningParameters)tuningParametersForRangeMode:(ASLayoutRangeMode)rangeMode rangeType:(ASLayoutRangeType)rangeType AS_WARN_UNUSED_RESULT ASDISPLAYNODE_DEPRECATED; +- (ASRangeTuningParameters)tuningParametersForRangeMode:(ASLayoutRangeMode)rangeMode rangeType:(ASLayoutRangeType)rangeType AS_WARN_UNUSED_RESULT ASDISPLAYNODE_DEPRECATED_MSG("Use ASTableNode method instead."); /** * Set the tuning parameters for a range type in the specified mode. @@ -122,14 +122,14 @@ NS_ASSUME_NONNULL_BEGIN * @see ASLayoutRangeMode * @see ASLayoutRangeType */ -- (void)setTuningParameters:(ASRangeTuningParameters)tuningParameters forRangeMode:(ASLayoutRangeMode)rangeMode rangeType:(ASLayoutRangeType)rangeType ASDISPLAYNODE_DEPRECATED; +- (void)setTuningParameters:(ASRangeTuningParameters)tuningParameters forRangeMode:(ASLayoutRangeMode)rangeMode rangeType:(ASLayoutRangeType)rangeType ASDISPLAYNODE_DEPRECATED_MSG("Use ASTableNode method instead."); /** * Similar to -visibleCells. * * @return an array containing the cell nodes being displayed on screen. */ -- (NSArray *)visibleNodes AS_WARN_UNUSED_RESULT ASDISPLAYNODE_DEPRECATED; +- (NSArray *)visibleNodes AS_WARN_UNUSED_RESULT ASDISPLAYNODE_DEPRECATED_MSG("Use ASTableNode method instead."); /** * Similar to -indexPathForCell:. @@ -138,7 +138,7 @@ NS_ASSUME_NONNULL_BEGIN * * @return an indexPath for this cellNode */ -- (nullable NSIndexPath *)indexPathForNode:(ASCellNode *)cellNode AS_WARN_UNUSED_RESULT ASDISPLAYNODE_DEPRECATED; +- (nullable NSIndexPath *)indexPathForNode:(ASCellNode *)cellNode AS_WARN_UNUSED_RESULT ASDISPLAYNODE_DEPRECATED_MSG("Use ASTableNode method instead."); /** * Reload everything from scratch, destroying the working range and all cached nodes. @@ -147,14 +147,14 @@ NS_ASSUME_NONNULL_BEGIN * the main thread. * @warning This method is substantially more expensive than UITableView's version. */ --(void)reloadDataWithCompletion:(void (^ _Nullable)())completion ASDISPLAYNODE_DEPRECATED; +-(void)reloadDataWithCompletion:(void (^ _Nullable)())completion ASDISPLAYNODE_DEPRECATED_MSG("Use ASTableNode method instead."); /** * Reload everything from scratch, destroying the working range and all cached nodes. * * @warning This method is substantially more expensive than UITableView's version. */ -- (void)reloadData ASDISPLAYNODE_DEPRECATED; +- (void)reloadData ASDISPLAYNODE_DEPRECATED_MSG("Use ASTableNode method instead."); /** * Reload everything from scratch entirely on the main thread, destroying the working range and all cached nodes. @@ -162,14 +162,14 @@ NS_ASSUME_NONNULL_BEGIN * @warning This method is substantially more expensive than UITableView's version and will block the main thread while * all the cells load. */ -- (void)reloadDataImmediately ASDISPLAYNODE_DEPRECATED; +- (void)reloadDataImmediately ASDISPLAYNODE_DEPRECATED_MSG("Use ASTableNode's reloadDataWithCompletion: followed by ASTableNode's -waitUntilAllUpdatesAreCommitted instead."); /** * Triggers a relayout of all nodes. * * @discussion This method invalidates and lays out every cell node in the table view. */ -- (void)relayoutItems ASDISPLAYNODE_DEPRECATED; +- (void)relayoutItems ASDISPLAYNODE_DEPRECATED_MSG("Use ASTableNode method instead."); /** * Begins a series of method calls that insert, delete, select, or reload rows and sections of the table view, with animation enabled and no completion block. @@ -180,7 +180,7 @@ NS_ASSUME_NONNULL_BEGIN * * @warning This method must be called from the main thread. */ -- (void)beginUpdates ASDISPLAYNODE_DEPRECATED; +- (void)beginUpdates ASDISPLAYNODE_DEPRECATED_MSG("Use ASTableNode's -performBatchUpdates:completion: instead."); /** * Concludes a series of method calls that insert, delete, select, or reload rows and sections of the table view, with animation enabled and no completion block. @@ -191,7 +191,7 @@ NS_ASSUME_NONNULL_BEGIN * * @warning This method is must be called from the main thread. */ -- (void)endUpdates ASDISPLAYNODE_DEPRECATED; +- (void)endUpdates ASDISPLAYNODE_DEPRECATED_MSG("Use ASTableNode's -performBatchUpdates:completion: instead."); /** * Concludes a series of method calls that insert, delete, select, or reload rows and sections of the table view. @@ -206,12 +206,12 @@ NS_ASSUME_NONNULL_BEGIN * Boolean parameter that contains the value YES if all of the related animations completed successfully or * NO if they were interrupted. This parameter may be nil. If supplied, the block is run on the main thread. */ -- (void)endUpdatesAnimated:(BOOL)animated completion:(void (^ _Nullable)(BOOL completed))completion ASDISPLAYNODE_DEPRECATED; +- (void)endUpdatesAnimated:(BOOL)animated completion:(void (^ _Nullable)(BOOL completed))completion ASDISPLAYNODE_DEPRECATED_MSG("Use ASTableNode's -performBatchUpdates:completion: instead."); /** * Blocks execution of the main thread until all section and row updates are committed. This method must be called from the main thread. */ -- (void)waitUntilAllUpdatesAreCommitted ASDISPLAYNODE_DEPRECATED; +- (void)waitUntilAllUpdatesAreCommitted ASDISPLAYNODE_DEPRECATED_MSG("Use ASTableNode method instead."); /** * Inserts one or more sections, with an option to animate the insertion. @@ -223,7 +223,7 @@ NS_ASSUME_NONNULL_BEGIN * @discussion This method must be called from the main thread. The asyncDataSource must be updated to reflect the changes * before this method is called. */ -- (void)insertSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation ASDISPLAYNODE_DEPRECATED; +- (void)insertSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation ASDISPLAYNODE_DEPRECATED_MSG("Use ASTableNode method instead."); /** * Deletes one or more sections, with an option to animate the deletion. @@ -235,7 +235,7 @@ NS_ASSUME_NONNULL_BEGIN * @discussion This method must be called from the main thread. The asyncDataSource must be updated to reflect the changes * before this method is called. */ -- (void)deleteSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation ASDISPLAYNODE_DEPRECATED; +- (void)deleteSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation ASDISPLAYNODE_DEPRECATED_MSG("Use ASTableNode method instead."); /** * Reloads the specified sections using a given animation effect. @@ -247,7 +247,7 @@ NS_ASSUME_NONNULL_BEGIN * @discussion This method must be called from the main thread. The asyncDataSource must be updated to reflect the changes * before this method is called. */ -- (void)reloadSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation ASDISPLAYNODE_DEPRECATED; +- (void)reloadSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation ASDISPLAYNODE_DEPRECATED_MSG("Use ASTableNode method instead."); /** * Moves a section to a new location. @@ -259,7 +259,7 @@ NS_ASSUME_NONNULL_BEGIN * @discussion This method must be called from the main thread. The asyncDataSource must be updated to reflect the changes * before this method is called. */ -- (void)moveSection:(NSInteger)section toSection:(NSInteger)newSection ASDISPLAYNODE_DEPRECATED; +- (void)moveSection:(NSInteger)section toSection:(NSInteger)newSection ASDISPLAYNODE_DEPRECATED_MSG("Use ASTableNode method instead."); /** * Inserts rows at the locations identified by an array of index paths, with an option to animate the insertion. @@ -271,7 +271,7 @@ NS_ASSUME_NONNULL_BEGIN * @discussion This method must be called from the main thread. The asyncDataSource must be updated to reflect the changes * before this method is called. */ -- (void)insertRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation ASDISPLAYNODE_DEPRECATED; +- (void)insertRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation ASDISPLAYNODE_DEPRECATED_MSG("Use ASTableNode method instead."); /** * Deletes the rows specified by an array of index paths, with an option to animate the deletion. @@ -283,7 +283,7 @@ NS_ASSUME_NONNULL_BEGIN * @discussion This method must be called from the main thread. The asyncDataSource must be updated to reflect the changes * before this method is called. */ -- (void)deleteRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation ASDISPLAYNODE_DEPRECATED; +- (void)deleteRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation ASDISPLAYNODE_DEPRECATED_MSG("Use ASTableNode method instead."); /** * Reloads the specified rows using a given animation effect. @@ -295,7 +295,7 @@ NS_ASSUME_NONNULL_BEGIN * @discussion This method must be called from the main thread. The asyncDataSource must be updated to reflect the changes * before this method is called. */ -- (void)reloadRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation ASDISPLAYNODE_DEPRECATED; +- (void)reloadRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation ASDISPLAYNODE_DEPRECATED_MSG("Use ASTableNode method instead."); /** * Moves the row at a specified location to a destination location. @@ -307,21 +307,21 @@ NS_ASSUME_NONNULL_BEGIN * @discussion This method must be called from the main thread. The asyncDataSource must be updated to reflect the changes * before this method is called. */ -- (void)moveRowAtIndexPath:(NSIndexPath *)indexPath toIndexPath:(NSIndexPath *)newIndexPath ASDISPLAYNODE_DEPRECATED; +- (void)moveRowAtIndexPath:(NSIndexPath *)indexPath toIndexPath:(NSIndexPath *)newIndexPath ASDISPLAYNODE_DEPRECATED_MSG("Use ASTableNode method instead."); /// Deprecated in 2.0. You should not call this method. -- (void)clearContents ASDISPLAYNODE_DEPRECATED; +- (void)clearContents ASDISPLAYNODE_DEPRECATED_MSG("You should not call this method directly. Intead, rely on the Interstate State callback methods."); /// Deprecated in 2.0. You should not call this method. -- (void)clearFetchedData ASDISPLAYNODE_DEPRECATED; +- (void)clearFetchedData ASDISPLAYNODE_DEPRECATED_MSG("You should not call this method directly. Intead, rely on the Interstate State callback methods."); @end -ASDISPLAYNODE_DEPRECATED +ASDISPLAYNODE_DEPRECATED_MSG("Renamed to ASTableDataSource.") @protocol ASTableViewDataSource @end -ASDISPLAYNODE_DEPRECATED +ASDISPLAYNODE_DEPRECATED_MSG("Renamed to ASTableDelegate.") @protocol ASTableViewDelegate @end diff --git a/AsyncDisplayKit/ASTableViewProtocols.h b/AsyncDisplayKit/ASTableViewProtocols.h index 9d2e220c65..00719dea26 100644 --- a/AsyncDisplayKit/ASTableViewProtocols.h +++ b/AsyncDisplayKit/ASTableViewProtocols.h @@ -19,9 +19,9 @@ NS_ASSUME_NONNULL_BEGIN @optional -- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section ASDISPLAYNODE_DEPRECATED; +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section ASDISPLAYNODE_DEPRECATED_MSG("Implement -tableNode:numberOfRowsInSection: instead."); -- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView ASDISPLAYNODE_DEPRECATED; +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView ASDISPLAYNODE_DEPRECATED_MSG("Implement numberOfSectionsInTableNode: instead."); - (nullable NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section; - (nullable NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section; @@ -62,14 +62,14 @@ NS_ASSUME_NONNULL_BEGIN - (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath; -- (BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED; -- (void)tableView:(UITableView *)tableView didHighlightRowAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED; -- (void)tableView:(UITableView *)tableView didUnhighlightRowAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED; +- (BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED_MSG("Implement -tableNode:shouldHighlightRowAtIndexPath: instead."); +- (void)tableView:(UITableView *)tableView didHighlightRowAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED_MSG("Implement -tableNode:didHighlightRowAtIndexPath: instead."); +- (void)tableView:(UITableView *)tableView didUnhighlightRowAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED_MSG("Implement -tableNode:didUnhighlightRowAtIndexPath: instead."); -- (nullable NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED; -- (nullable NSIndexPath *)tableView:(UITableView *)tableView willDeselectRowAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED; -- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED; -- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED; +- (nullable NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED_MSG("Implement -tableNode:willSelectRowAtIndexPath: instead."); +- (nullable NSIndexPath *)tableView:(UITableView *)tableView willDeselectRowAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED_MSG("Implement -tableNode:willDeselectRowAtIndexPath: instead."); +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED_MSG("Implement -tableNode:didSelectRowAtIndexPath: instead."); +- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED_MSG("Implement -tableNode:didDeselectRowAtIndexPath: instead."); - (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath; - (nullable NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath; @@ -85,9 +85,9 @@ NS_ASSUME_NONNULL_BEGIN - (NSInteger)tableView:(UITableView *)tableView indentationLevelForRowAtIndexPath:(NSIndexPath *)indexPath; -- (BOOL)tableView:(UITableView *)tableView shouldShowMenuForRowAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED; -- (BOOL)tableView:(UITableView *)tableView canPerformAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(nullable id)sender ASDISPLAYNODE_DEPRECATED; -- (void)tableView:(UITableView *)tableView performAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(nullable id)sender ASDISPLAYNODE_DEPRECATED; +- (BOOL)tableView:(UITableView *)tableView shouldShowMenuForRowAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED_MSG("Implement -tableNode:shouldShowMenuForRowAtIndexPath: instead."); +- (BOOL)tableView:(UITableView *)tableView canPerformAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(nullable id)sender ASDISPLAYNODE_DEPRECATED_MSG("Implement -tableNode:canPerformAction:forRowAtIndexPath:withSender: instead."); +- (void)tableView:(UITableView *)tableView performAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(nullable id)sender ASDISPLAYNODE_DEPRECATED_MSG("Implement -tableNode:performAction:forRowAtIndexPath:withSender: instead."); @end diff --git a/AsyncDisplayKit/ASTextNode.h b/AsyncDisplayKit/ASTextNode.h index 354039e238..78bdd12005 100644 --- a/AsyncDisplayKit/ASTextNode.h +++ b/AsyncDisplayKit/ASTextNode.h @@ -299,7 +299,7 @@ typedef NS_ENUM(NSUInteger, ASTextNodeHighlightStyle) { @see attributedText */ -@property (nullable, nonatomic, copy) NSAttributedString *attributedString ASDISPLAYNODE_DEPRECATED; +@property (nullable, nonatomic, copy) NSAttributedString *attributedString ASDISPLAYNODE_DEPRECATED_MSG("Use .attributedText instead."); /** @@ -308,8 +308,10 @@ typedef NS_ENUM(NSUInteger, ASTextNodeHighlightStyle) { @see truncationAttributedText */ -@property (nullable, nonatomic, copy) NSAttributedString *truncationAttributedString ASDISPLAYNODE_DEPRECATED; +@property (nullable, nonatomic, copy) NSAttributedString *truncationAttributedString ASDISPLAYNODE_DEPRECATED_MSG("Use .truncationAttributedText instead."); @end NS_ASSUME_NONNULL_END + + diff --git a/AsyncDisplayKit/Details/ASCollectionViewFlowLayoutInspector.h b/AsyncDisplayKit/Details/ASCollectionViewFlowLayoutInspector.h index e0e560ecf8..3c34bfc909 100644 --- a/AsyncDisplayKit/Details/ASCollectionViewFlowLayoutInspector.h +++ b/AsyncDisplayKit/Details/ASCollectionViewFlowLayoutInspector.h @@ -66,7 +66,7 @@ NS_ASSUME_NONNULL_BEGIN * @deprecated This method will not be called, and it is only deprecated as a reminder to remove it. * Supplementary elements must exist in the same sections as regular collection view items i.e. -numberOfSectionsInCollectionView: */ -- (NSUInteger)collectionView:(ASCollectionView *)collectionView numberOfSectionsForSupplementaryNodeOfKind:(NSString *)kind ASDISPLAYNODE_DEPRECATED; +- (NSUInteger)collectionView:(ASCollectionView *)collectionView numberOfSectionsForSupplementaryNodeOfKind:(NSString *)kind ASDISPLAYNODE_DEPRECATED_MSG("Use ASCollectionNode's method instead."); @end diff --git a/AsyncDisplayKit/Details/ASIndexPath.m b/AsyncDisplayKit/Details/ASIndexPath.m index 8c2234e639..bca083d5fc 100644 --- a/AsyncDisplayKit/Details/ASIndexPath.m +++ b/AsyncDisplayKit/Details/ASIndexPath.m @@ -64,7 +64,7 @@ BOOL ASIndexPathRangeEqualToIndexPathRange(ASIndexPathRange first, ASIndexPathRa + (NSIndexPath *)indexPathWithASIndexPath:(ASIndexPath)indexPath { - return [NSIndexPath indexPathForRow:indexPath.row inSection:indexPath.section];; + return [NSIndexPath indexPathForRow:indexPath.row inSection:indexPath.section]; } - (ASIndexPath)ASIndexPathValue diff --git a/AsyncDisplayKit/Layout/ASDimension.h b/AsyncDisplayKit/Layout/ASDimension.h index 675e62a264..37b8880e2e 100644 --- a/AsyncDisplayKit/Layout/ASDimension.h +++ b/AsyncDisplayKit/Layout/ASDimension.h @@ -336,7 +336,7 @@ ASDISPLAYNODE_INLINE AS_WARN_UNUSED_RESULT ASSizeRange ASLayoutElementSizeResolv /** * Function is deprecated. Use ASSizeRangeMakeWithExactCGSize instead. */ -extern AS_WARN_UNUSED_RESULT ASSizeRange ASSizeRangeMakeExactSize(CGSize size) ASDISPLAYNODE_DEPRECATED; +extern AS_WARN_UNUSED_RESULT ASSizeRange ASSizeRangeMakeExactSize(CGSize size) ASDISPLAYNODE_DEPRECATED_MSG("Use ASSizeRangeMakeWithExactCGSize instead."); NS_ASSUME_NONNULL_END ASDISPLAYNODE_EXTERN_C_END diff --git a/AsyncDisplayKit/Layout/ASLayoutElement.h b/AsyncDisplayKit/Layout/ASLayoutElement.h index b55aeb0c2c..0f22d2c343 100644 --- a/AsyncDisplayKit/Layout/ASLayoutElement.h +++ b/AsyncDisplayKit/Layout/ASLayoutElement.h @@ -145,9 +145,9 @@ NS_ASSUME_NONNULL_BEGIN * * @return An ASLayout instance defining the layout of the receiver and its children. * - * @deprecated Deprecated in version 2.0: Use ASCalculateRootLayout or ASCalculateLayout instead + * @deprecated Deprecated in version 2.0: Use ASCalculateRootLayout() or ASCalculateLayout() instead */ -- (ASLayout *)measureWithSizeRange:(ASSizeRange)constrainedSize ASDISPLAYNODE_DEPRECATED; +- (ASLayout *)measureWithSizeRange:(ASSizeRange)constrainedSize ASDISPLAYNODE_DEPRECATED_MSG("Use layoutThatFits: instead"); @end diff --git a/AsyncDisplayKit/Layout/ASLayoutSpec.h b/AsyncDisplayKit/Layout/ASLayoutSpec.h index 261066b017..cce02aaee4 100644 --- a/AsyncDisplayKit/Layout/ASLayoutSpec.h +++ b/AsyncDisplayKit/Layout/ASLayoutSpec.h @@ -75,7 +75,7 @@ NS_ASSUME_NONNULL_BEGIN /* * Returns an ASWrapperLayoutSpec object initialized with the given layoutElement as child */ -- (instancetype)initWithLayoutElement:(id)layoutElement NS_DESIGNATED_INITIALIZER;; +- (instancetype)initWithLayoutElement:(id)layoutElement NS_DESIGNATED_INITIALIZER; /* * Init not available for ASWrapperLayoutSpec diff --git a/AsyncDisplayKit/Layout/ASLayoutSpec.mm b/AsyncDisplayKit/Layout/ASLayoutSpec.mm index 2b5a31be38..f7d5bd77f9 100644 --- a/AsyncDisplayKit/Layout/ASLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASLayoutSpec.mm @@ -128,7 +128,7 @@ - (void)setChild:(id)child { - ASDisplayNodeAssert(self.isMutable, @"Cannot set properties when layout spec is not mutable");; + ASDisplayNodeAssert(self.isMutable, @"Cannot set properties when layout spec is not mutable"); ASDisplayNodeAssert(_childrenArray.count < 2, @"This layout spec does not support more than one child. Use the setChildren: or the setChild:AtIndex: API"); if (child) { diff --git a/AsyncDisplayKit/Private/_AS-objc-internal.h b/AsyncDisplayKit/Private/_AS-objc-internal.h index f050602a19..535c212e5e 100644 --- a/AsyncDisplayKit/Private/_AS-objc-internal.h +++ b/AsyncDisplayKit/Private/_AS-objc-internal.h @@ -441,7 +441,7 @@ typedef enum { -(BOOL)_tryRetain { \ __typeof__(_rc_ivar) _prev; \ do { \ - _prev = __atomic_load_n(&_rc_ivar, __ATOMIC_SEQ_CST);; \ + _prev = __atomic_load_n(&_rc_ivar, __ATOMIC_SEQ_CST); \ if (_prev & 1) { \ return 0; \ } else if (_prev == -2) { \ diff --git a/Base/ASBaseDefines.h b/Base/ASBaseDefines.h index 265c1544de..a470087afe 100755 --- a/Base/ASBaseDefines.h +++ b/Base/ASBaseDefines.h @@ -74,12 +74,8 @@ # define ASDISPLAYNODE_WARN_DEPRECATED 1 #endif -#ifndef ASDISPLAYNODE_DEPRECATED -# if ASDISPLAYNODE_GNUC (3, 0) && ASDISPLAYNODE_WARN_DEPRECATED -# define ASDISPLAYNODE_DEPRECATED __attribute__ ((deprecated)) -# else -# define ASDISPLAYNODE_DEPRECATED -# endif +#ifndef ASDISPLAYNODE_DEPRECATED_MSG +# define ASDISPLAYNODE_DEPRECATED_MSG(msg) __deprecated_msg(msg) #endif #if defined (__cplusplus) && defined (__GNUC__) From a705ed09cbf18569b713f7ec036bb12a886c71ff Mon Sep 17 00:00:00 2001 From: Hannah Troisi Date: Wed, 19 Oct 2016 16:05:54 -0700 Subject: [PATCH 16/59] fix macro (#2439) --- Base/ASBaseDefines.h | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/Base/ASBaseDefines.h b/Base/ASBaseDefines.h index a470087afe..6bf7d2f9f9 100755 --- a/Base/ASBaseDefines.h +++ b/Base/ASBaseDefines.h @@ -74,8 +74,18 @@ # define ASDISPLAYNODE_WARN_DEPRECATED 1 #endif +#ifndef ASDISPLAYNODE_DEPRECATED +# if ASDISPLAYNODE_GNUC (3, 0) && ASDISPLAYNODE_WARN_DEPRECATED +# define ASDISPLAYNODE_DEPRECATED __attribute__ ((deprecated)) +# else +# define ASDISPLAYNODE_DEPRECATED +# endif +#endif + #ifndef ASDISPLAYNODE_DEPRECATED_MSG -# define ASDISPLAYNODE_DEPRECATED_MSG(msg) __deprecated_msg(msg) +# if ASDISPLAYNODE_GNUC (3, 0) && ASDISPLAYNODE_WARN_DEPRECATED +# define ASDISPLAYNODE_DEPRECATED_MSG(msg) __deprecated_msg(msg) +# endif #endif #if defined (__cplusplus) && defined (__GNUC__) From 4816d75fbd07921286e323cc5e8298a06ba21755 Mon Sep 17 00:00:00 2001 From: Garrett Moon Date: Wed, 19 Oct 2016 16:31:26 -0700 Subject: [PATCH 17/59] Macro still needs to be defined even if we're skipping. (#2441) --- Base/ASBaseDefines.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Base/ASBaseDefines.h b/Base/ASBaseDefines.h index 6bf7d2f9f9..bfa3de4aec 100755 --- a/Base/ASBaseDefines.h +++ b/Base/ASBaseDefines.h @@ -85,6 +85,8 @@ #ifndef ASDISPLAYNODE_DEPRECATED_MSG # if ASDISPLAYNODE_GNUC (3, 0) && ASDISPLAYNODE_WARN_DEPRECATED # define ASDISPLAYNODE_DEPRECATED_MSG(msg) __deprecated_msg(msg) +# else +# define ASDISPLAYNODE_DEPRECATED_MSG(msg) # endif #endif From dbe3b1bd71435421ceaf92f6cdc0d3ce7b8e8bb3 Mon Sep 17 00:00:00 2001 From: Adlai Holler Date: Thu, 20 Oct 2016 12:53:25 -0700 Subject: [PATCH 18/59] Remove block copying (#2438) --- AsyncDisplayKit/ASDisplayNode.mm | 2 +- AsyncDisplayKit/ASImageNode.mm | 2 +- AsyncDisplayKit/ASRunLoopQueue.mm | 2 +- .../Transactions/_ASAsyncTransaction.mm | 4 ++-- .../Private/ASDisplayNode+AsyncDisplay.mm | 19 ++++++++++++------- 5 files changed, 17 insertions(+), 12 deletions(-) diff --git a/AsyncDisplayKit/ASDisplayNode.mm b/AsyncDisplayKit/ASDisplayNode.mm index 95a4a55f86..0bcf8afdb5 100644 --- a/AsyncDisplayKit/ASDisplayNode.mm +++ b/AsyncDisplayKit/ASDisplayNode.mm @@ -2505,7 +2505,7 @@ void recursivelyTriggerDisplayForLayer(CALayer *layer, BOOL shouldBlock) ASDisplayNodeAssert(!(_methodOverrides & ASDisplayNodeMethodOverrideLayoutSpecThatFits), @"Overwriting layoutSpecThatFits: and providing a layoutSpecBlock block is currently not supported"); ASDN::MutexLocker l(__instanceLock__); - _layoutSpecBlock = [layoutSpecBlock copy]; + _layoutSpecBlock = layoutSpecBlock; } - (ASLayoutSpecBlock)layoutSpecBlock diff --git a/AsyncDisplayKit/ASImageNode.mm b/AsyncDisplayKit/ASImageNode.mm index 1f0845b402..1aa0c22587 100644 --- a/AsyncDisplayKit/ASImageNode.mm +++ b/AsyncDisplayKit/ASImageNode.mm @@ -526,7 +526,7 @@ static ASDN::Mutex cacheLock; // Stash the block and call-site queue. We'll invoke it in -displayDidFinish. ASDN::MutexLocker l(__instanceLock__); if (_displayCompletionBlock != displayCompletionBlock) { - _displayCompletionBlock = [displayCompletionBlock copy]; + _displayCompletionBlock = displayCompletionBlock; } [self setNeedsDisplay]; diff --git a/AsyncDisplayKit/ASRunLoopQueue.mm b/AsyncDisplayKit/ASRunLoopQueue.mm index 42e5ea96e7..aac7ad1d17 100644 --- a/AsyncDisplayKit/ASRunLoopQueue.mm +++ b/AsyncDisplayKit/ASRunLoopQueue.mm @@ -164,7 +164,7 @@ static void runLoopSourceCallback(void *info) { if (self = [super init]) { _runLoop = runloop; _internalQueue = std::deque(); - _queueConsumer = [handlerBlock copy]; + _queueConsumer = handlerBlock; _batchSize = 1; _ensureExclusiveMembership = YES; diff --git a/AsyncDisplayKit/Details/Transactions/_ASAsyncTransaction.mm b/AsyncDisplayKit/Details/Transactions/_ASAsyncTransaction.mm index 82ddb2a686..55824942ce 100644 --- a/AsyncDisplayKit/Details/Transactions/_ASAsyncTransaction.mm +++ b/AsyncDisplayKit/Details/Transactions/_ASAsyncTransaction.mm @@ -36,7 +36,7 @@ NSInteger const ASDefaultTransactionPriority = 0; - (instancetype)initWithOperationCompletionBlock:(asyncdisplaykit_async_transaction_operation_completion_block_t)operationCompletionBlock { if ((self = [super init])) { - _operationCompletionBlock = [operationCompletionBlock copy]; + _operationCompletionBlock = operationCompletionBlock; } return self; } @@ -339,7 +339,7 @@ ASAsyncTransactionQueue & ASAsyncTransactionQueue::instance() callbackQueue = dispatch_get_main_queue(); } _callbackQueue = callbackQueue; - _completionBlock = [completionBlock copy]; + _completionBlock = completionBlock; _state = ATOMIC_VAR_INIT(ASAsyncTransactionStateOpen); } diff --git a/AsyncDisplayKit/Private/ASDisplayNode+AsyncDisplay.mm b/AsyncDisplayKit/Private/ASDisplayNode+AsyncDisplay.mm index 9fedcb1b4d..484b6b76a9 100644 --- a/AsyncDisplayKit/Private/ASDisplayNode+AsyncDisplay.mm +++ b/AsyncDisplayKit/Private/ASDisplayNode+AsyncDisplay.mm @@ -120,7 +120,7 @@ } } }; - [displayBlocks addObject:[pushAndDisplayBlock copy]]; + [displayBlocks addObject:pushAndDisplayBlock]; } // Recursively capture displayBlocks for all descendants. @@ -130,11 +130,16 @@ // If we pushed a transform, pop it by adding a display block that does nothing other than that. if (shouldDisplay) { - dispatch_block_t popBlock = ^{ - CGContextRef context = UIGraphicsGetCurrentContext(); - CGContextRestoreGState(context); - }; - [displayBlocks addObject:[popBlock copy]]; + // Since this block is pure, we can store it statically. + static dispatch_block_t popBlock; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + popBlock = ^{ + CGContextRef context = UIGraphicsGetCurrentContext(); + CGContextRestoreGState(context); + }; + }); + [displayBlocks addObject:popBlock]; } } @@ -252,7 +257,7 @@ }; } - return [displayBlock copy]; + return displayBlock; } - (void)displayAsyncLayer:(_ASDisplayLayer *)asyncLayer asynchronously:(BOOL)asynchronously From d0421195ebb9f7ed046b841ba9350b938ea94a9c Mon Sep 17 00:00:00 2001 From: Adlai Holler Date: Thu, 20 Oct 2016 14:32:01 -0700 Subject: [PATCH 19/59] Make flow layout inspector call the new constrainedSize method (#2444) --- .../Details/ASCollectionViewFlowLayoutInspector.m | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/AsyncDisplayKit/Details/ASCollectionViewFlowLayoutInspector.m b/AsyncDisplayKit/Details/ASCollectionViewFlowLayoutInspector.m index d82aa45a58..504d0d5f2b 100644 --- a/AsyncDisplayKit/Details/ASCollectionViewFlowLayoutInspector.m +++ b/AsyncDisplayKit/Details/ASCollectionViewFlowLayoutInspector.m @@ -104,7 +104,8 @@ static inline ASSizeRange NodeConstrainedSizeForScrollDirection(ASCollectionView struct { unsigned int implementsReferenceSizeForHeader:1; unsigned int implementsReferenceSizeForFooter:1; - unsigned int implementsConstrainedSizeForNodeAtIndexPath:1; + unsigned int implementsConstrainedSizeForNodeAtIndexPathDeprecated:1; + unsigned int implementsConstrainedSizeForItemAtIndexPath:1; } _delegateFlags; struct { @@ -137,7 +138,8 @@ static inline ASSizeRange NodeConstrainedSizeForScrollDirection(ASCollectionView } else { _delegateFlags.implementsReferenceSizeForHeader = [delegate respondsToSelector:@selector(collectionView:layout:referenceSizeForHeaderInSection:)]; _delegateFlags.implementsReferenceSizeForFooter = [delegate respondsToSelector:@selector(collectionView:layout:referenceSizeForFooterInSection:)]; - _delegateFlags.implementsConstrainedSizeForNodeAtIndexPath = [delegate respondsToSelector:@selector(collectionView:constrainedSizeForNodeAtIndexPath:)]; + _delegateFlags.implementsConstrainedSizeForNodeAtIndexPathDeprecated = [delegate respondsToSelector:@selector(collectionView:constrainedSizeForNodeAtIndexPath:)]; + _delegateFlags.implementsConstrainedSizeForItemAtIndexPath = [delegate respondsToSelector:@selector(collectionNode:constrainedSizeForItemAtIndexPath:)]; } } @@ -152,7 +154,9 @@ static inline ASSizeRange NodeConstrainedSizeForScrollDirection(ASCollectionView - (ASSizeRange)collectionView:(ASCollectionView *)collectionView constrainedSizeForNodeAtIndexPath:(NSIndexPath *)indexPath { - if (_delegateFlags.implementsConstrainedSizeForNodeAtIndexPath) { + if (_delegateFlags.implementsConstrainedSizeForItemAtIndexPath) { + return [collectionView.asyncDelegate collectionNode:collectionView.collectionNode constrainedSizeForItemAtIndexPath:indexPath]; + } else if (_delegateFlags.implementsConstrainedSizeForNodeAtIndexPathDeprecated) { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" return [collectionView.asyncDelegate collectionView:collectionView constrainedSizeForNodeAtIndexPath:indexPath]; From 41c0781aa9f47acc7592ae6875e8c55ffe87026f Mon Sep 17 00:00:00 2001 From: Adlai Holler Date: Thu, 20 Oct 2016 14:41:11 -0700 Subject: [PATCH 20/59] Update exception test for new constrainedSize method (#2445) --- .../ASCollectionViewFlowLayoutInspectorTests.m | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/AsyncDisplayKitTests/ASCollectionViewFlowLayoutInspectorTests.m b/AsyncDisplayKitTests/ASCollectionViewFlowLayoutInspectorTests.m index 22b2768d6d..443e1d7534 100644 --- a/AsyncDisplayKitTests/ASCollectionViewFlowLayoutInspectorTests.m +++ b/AsyncDisplayKitTests/ASCollectionViewFlowLayoutInspectorTests.m @@ -402,22 +402,24 @@ - (void)testThatItThrowsIfNodeConstrainedSizeIsImplementedOnDataSourceButNotOnDelegateFlowLayoutInspector { UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init]; - ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout]; + ASCollectionNode *node = [[ASCollectionNode alloc] initWithCollectionViewLayout:layout]; + ASCollectionView *collectionView = node.view; id dataSourceAndDelegate = [OCMockObject mockForProtocol:@protocol(InspectorTestDataSourceDelegateProtocol)]; ASSizeRange constrainedSize = ASSizeRangeMake(CGSizeZero, CGSizeZero); NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:0]; NSValue *value = [NSValue value:&constrainedSize withObjCType:@encode(ASSizeRange)]; - [[[dataSourceAndDelegate stub] andReturnValue:value] collectionView:collectionView constrainedSizeForNodeAtIndexPath:indexPath]; - collectionView.asyncDataSource = dataSourceAndDelegate; + [[[dataSourceAndDelegate stub] andReturnValue:value] collectionNode:node constrainedSizeForItemAtIndexPath:indexPath]; + node.dataSource = dataSourceAndDelegate; id delegate = [InspectorTestDataSourceDelegateWithoutNodeConstrainedSize new]; - collectionView.asyncDelegate = delegate; + node.delegate = delegate; ASCollectionViewFlowLayoutInspector *inspector = collectionView.layoutInspector; + XCTAssertThrows([inspector collectionView:collectionView constrainedSizeForNodeAtIndexPath:indexPath]); - collectionView.asyncDelegate = dataSourceAndDelegate; + node.delegate = dataSourceAndDelegate; XCTAssertNoThrow([inspector collectionView:collectionView constrainedSizeForNodeAtIndexPath:indexPath]); } From 46cf1e3032ac78780ee25d2e483bb129c8b99273 Mon Sep 17 00:00:00 2001 From: Garrett Moon Date: Thu, 20 Oct 2016 15:43:32 -0700 Subject: [PATCH 21/59] Fix asdk again (#2446) * Man whoever is maintaining PINRemoteImage really needs to get theirselves together! * Learning from previous mistakes, we should set a specific version on this. --- AsyncDisplayKit.podspec | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/AsyncDisplayKit.podspec b/AsyncDisplayKit.podspec index 9e146ed38d..f5dba4322d 100644 --- a/AsyncDisplayKit.podspec +++ b/AsyncDisplayKit.podspec @@ -59,8 +59,7 @@ Pod::Spec.new do |spec| spec.subspec 'PINRemoteImage' do |pin| pin.xcconfig = { 'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) PIN_REMOTE_IMAGE=1' } - pin.dependency 'PINRemoteImage/iOS', '>= 3.0.0-beta.4' - pin.dependency 'PINRemoteImage/PINCache' + pin.dependency 'PINRemoteImage/iOS', '= 3.0.0-beta.5' pin.dependency 'AsyncDisplayKit/Core' end From 1fbcefdbd3608419c7eeafde8a7f6d39af955898 Mon Sep 17 00:00:00 2001 From: Hannah Troisi Date: Thu, 20 Oct 2016 17:09:50 -0700 Subject: [PATCH 22/59] [Examples] Refactor ASMapNode (#2383) * Refactor example & test Layout API * fix layoutSpecThatFits: * remove test code * address @appleguy's comments * remove project file * remove workspace * Fix Uncalled Collection Delegate Methods (#2433) * Fix batch fetching * Fix not calling constrainedSizeForItemAtIndexPath: * Fix constrainedSizeForItemAtIndexPath: not being called * Add preferredSize as getter to ASLayoutElementStyle (#2427) * [2.0] add helpful deprecation messages (#2437) [2.0] add helpful deprecation messages * fix macro (#2439) * Macro still needs to be defined even if we're skipping. (#2441) * Remove block copying (#2438) * Make flow layout inspector call the new constrainedSize method (#2444) * Update exception test for new constrainedSize method (#2445) * Fix asdk again (#2446) * Man whoever is maintaining PINRemoteImage really needs to get theirselves together! * Learning from previous mistakes, we should set a specific version on this. * Refactor example & test Layout API * fix layoutSpecThatFits: * remove test code * address @appleguy's comments * remove project file * remove workspace --- examples/ASMapNode/Sample/AppDelegate.m | 4 +- examples/ASMapNode/Sample/MapHandlerNode.m | 265 +++++++++++---------- examples/ASMapNode/Sample/ViewController.m | 11 +- 3 files changed, 144 insertions(+), 136 deletions(-) diff --git a/examples/ASMapNode/Sample/AppDelegate.m b/examples/ASMapNode/Sample/AppDelegate.m index e56bcd4ec0..7cf75f8bb7 100644 --- a/examples/ASMapNode/Sample/AppDelegate.m +++ b/examples/ASMapNode/Sample/AppDelegate.m @@ -24,12 +24,14 @@ @implementation AppDelegate -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions +{ // Override point for customization after application launch. self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; self.window.backgroundColor = [UIColor whiteColor]; self.window.rootViewController = [[UINavigationController alloc] initWithRootViewController:[ViewController new]]; [self.window makeKeyAndVisible]; + return YES; } diff --git a/examples/ASMapNode/Sample/MapHandlerNode.m b/examples/ASMapNode/Sample/MapHandlerNode.m index 1a1cd8e314..33e09a5b69 100644 --- a/examples/ASMapNode/Sample/MapHandlerNode.m +++ b/examples/ASMapNode/Sample/MapHandlerNode.m @@ -18,24 +18,18 @@ #import "MapHandlerNode.h" #import "CustomMapAnnotation.h" -#import - -#import -#import -#import - -#import -#import +#import +#import @interface MapHandlerNode () -@property (nonatomic, strong) ASEditableTextNode * latEditableNode; -@property (nonatomic, strong) ASEditableTextNode * lonEditableNode; -@property (nonatomic, strong) ASEditableTextNode * deltaLatEditableNode; -@property (nonatomic, strong) ASEditableTextNode * deltaLonEditableNode; -@property (nonatomic, strong) ASButtonNode * updateRegionButton; -@property (nonatomic, strong) ASButtonNode * liveMapToggleButton; -@property (nonatomic, strong) ASMapNode * mapNode; +@property (nonatomic, strong) ASEditableTextNode *latEditableNode; +@property (nonatomic, strong) ASEditableTextNode *lonEditableNode; +@property (nonatomic, strong) ASEditableTextNode *deltaLatEditableNode; +@property (nonatomic, strong) ASEditableTextNode *deltaLonEditableNode; +@property (nonatomic, strong) ASButtonNode *updateRegionButton; +@property (nonatomic, strong) ASButtonNode *liveMapToggleButton; +@property (nonatomic, strong) ASMapNode *mapNode; @end @@ -47,25 +41,45 @@ { if (!(self = [super init])) return nil; + + self.automaticallyManagesSubnodes = YES; + + _mapNode = [[ASMapNode alloc] init]; + _mapNode.mapDelegate = self; _latEditableNode = [[ASEditableTextNode alloc] init]; _lonEditableNode = [[ASEditableTextNode alloc] init]; _deltaLatEditableNode = [[ASEditableTextNode alloc] init]; _deltaLonEditableNode = [[ASEditableTextNode alloc] init]; - _updateRegionButton = [[ASButtonNode alloc] init]; - _liveMapToggleButton = [[ASButtonNode alloc] init]; - _mapNode = [[ASMapNode alloc] init]; - - [self addSubnode:_latEditableNode]; - [self addSubnode:_lonEditableNode]; - [self addSubnode:_deltaLatEditableNode]; - [self addSubnode:_deltaLonEditableNode]; - - [self addSubnode:_updateRegionButton]; - [self addSubnode:_liveMapToggleButton]; - [self addSubnode:_mapNode]; - + _updateRegionButton = [[ASButtonNode alloc] init]; + _liveMapToggleButton = [[ASButtonNode alloc] init]; + + UIImage *backgroundImage = [UIImage as_resizableRoundedImageWithCornerRadius:5 + cornerColor:[UIColor whiteColor] + fillColor:[UIColor lightGrayColor]]; + + UIImage *backgroundHiglightedImage = [UIImage as_resizableRoundedImageWithCornerRadius:5 + cornerColor:[UIColor whiteColor] + fillColor:[[UIColor lightGrayColor] colorWithAlphaComponent:0.4] + borderColor:[UIColor lightGrayColor] + borderWidth:2.0]; + + [_updateRegionButton setBackgroundImage:backgroundImage forState:ASControlStateNormal]; + [_updateRegionButton setBackgroundImage:backgroundHiglightedImage forState:ASControlStateHighlighted]; + + [_liveMapToggleButton setBackgroundImage:backgroundImage forState:ASControlStateNormal]; + [_liveMapToggleButton setBackgroundImage:backgroundHiglightedImage forState:ASControlStateHighlighted]; + + _updateRegionButton.contentEdgeInsets = UIEdgeInsetsMake(5, 5, 5, 5); + [_updateRegionButton setTitle:@"Update Region" withFont:nil withColor:[UIColor blueColor] forState:ASControlStateNormal]; + + [_updateRegionButton addTarget:self action:@selector(updateRegion) forControlEvents:ASControlNodeEventTouchUpInside]; + + [_liveMapToggleButton setTitle:[self liveMapStr] withFont:nil withColor:[UIColor blueColor] forState:ASControlStateNormal]; + + [_liveMapToggleButton addTarget:self action:@selector(toggleLiveMap) forControlEvents:ASControlNodeEventTouchUpInside]; + return self; } @@ -73,24 +87,12 @@ { [super didLoad]; - _latEditableNode.attributedText = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"%f", _mapNode.region.center.latitude]]; - _lonEditableNode.attributedText = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"%f", _mapNode.region.center.longitude]]; - _deltaLatEditableNode.attributedText = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"%f", _mapNode.region.span.latitudeDelta]]; - _deltaLonEditableNode.attributedText = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"%f", _mapNode.region.span.longitudeDelta]]; - [self configureEditableNodes:_latEditableNode]; [self configureEditableNodes:_lonEditableNode]; [self configureEditableNodes:_deltaLatEditableNode]; [self configureEditableNodes:_deltaLonEditableNode]; - - _mapNode.mapDelegate = self; - - [_updateRegionButton setTitle:@"Update Region" withFont:nil withColor:[UIColor blueColor] forState:ASControlStateNormal]; - [_updateRegionButton setTitle:@"Update Region" withFont:[UIFont systemFontOfSize:14] withColor:[UIColor blueColor] forState:ASControlStateHighlighted]; - [_updateRegionButton addTarget:self action:@selector(updateRegion) forControlEvents:ASControlNodeEventTouchUpInside]; - [_liveMapToggleButton setTitle:[self liveMapStr] withFont:nil withColor:[UIColor blueColor] forState:ASControlStateNormal]; - [_liveMapToggleButton setTitle:[self liveMapStr] withFont:[UIFont systemFontOfSize:14] withColor:[UIColor blueColor] forState:ASControlStateHighlighted]; - [_liveMapToggleButton addTarget:self action:@selector(toggleLiveMap) forControlEvents:ASControlNodeEventTouchUpInside]; + + [self updateLocationTextWithMKCoordinateRegion:_mapNode.region]; // avoiding retain cycles __weak MapHandlerNode *weakSelf = self; @@ -109,90 +111,87 @@ [self addAnnotations]; } -#pragma mark - Layout - -- (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize -{ +/** + * ---------------------------------ASStackLayoutSpec-------------------------------- + * | ------------------------------ASInsetLayoutSpec----------------------------- | + * | | ---------------------------ASStackLayoutSpec-------------------------- | | + * | | | -----------------ASStackLayoutSpec---------------- | | | + * | | | | --------------ASStackLayoutSpec------------- | | | | + * | | | | | ASEditableTextNode ASEditableTextNode | | | | | + * | | | | -------------------------------------------- | | | | + * | | | | --------------ASStackLayoutSpec------------- | ASButtonNode | | | + * | | | | | ASEditableTextNode ASEditableTextNode | | | | | + * | | | | -------------------------------------------- | | | | + * | | | -------------------------------------------------- | | | + * | | ---------------------------------------------------------------------- | | + * | ---------------------------------------------------------------------------- | + * | ASButtonNode | + * | ASMapNode | + * ---------------------------------------------------------------------------------- + * + * This diagram was created by setting a breakpoint on the returned `layoutSpec` + * and calling "po [layoutSpec asciiArtString]" in the debugger. + */ #define SPACING 5 #define HEIGHT 30 - CGSize nodeSize = CGSizeMake(constrainedSize.max.width * 0.3, HEIGHT); +- (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize +{ + _latEditableNode.style.width = ASDimensionMake(@"50%"); + _lonEditableNode.style.width = ASDimensionMake(@"50%"); + _deltaLatEditableNode.style.width = ASDimensionMake(@"50%"); + _deltaLonEditableNode.style.width = ASDimensionMake(@"50%"); - _latEditableNode.style.preferredSize = nodeSize; - _lonEditableNode.style.preferredSize = nodeSize; + _liveMapToggleButton.style.maxHeight = ASDimensionMake(HEIGHT); - _deltaLatEditableNode.style.preferredSize = nodeSize; - _deltaLonEditableNode.style.preferredSize = nodeSize; + _mapNode.style.flexGrow = 1.0; + + ASStackLayoutSpec *lonlatSpec = [ASStackLayoutSpec stackLayoutSpecWithDirection:ASStackLayoutDirectionHorizontal + spacing:SPACING + justifyContent:ASStackLayoutJustifyContentStart + alignItems:ASStackLayoutAlignItemsCenter + children:@[_latEditableNode, _lonEditableNode]]; + + ASStackLayoutSpec *deltaLonlatSpec = [ASStackLayoutSpec stackLayoutSpecWithDirection:ASStackLayoutDirectionHorizontal + spacing:SPACING + justifyContent:ASStackLayoutJustifyContentSpaceBetween + alignItems:ASStackLayoutAlignItemsCenter + children:@[_deltaLatEditableNode, _deltaLonEditableNode]]; + + ASStackLayoutSpec *lonlatConfigSpec = [ASStackLayoutSpec stackLayoutSpecWithDirection:ASStackLayoutDirectionVertical + spacing:SPACING + justifyContent:ASStackLayoutJustifyContentStart + alignItems:ASStackLayoutAlignItemsStretch + children:@[lonlatSpec, deltaLonlatSpec]]; - _updateRegionButton.style.preferredSize = nodeSize; - _liveMapToggleButton.style.preferredSize = nodeSize; + lonlatConfigSpec.style.flexGrow = 1.0; - _latEditableNode.style.flexGrow = _lonEditableNode.style.flexGrow = YES; - _deltaLatEditableNode.style.flexGrow = _deltaLonEditableNode.style.flexGrow = YES; - _updateRegionButton.style.flexGrow = _liveMapToggleButton.style.flexGrow = YES; + ASStackLayoutSpec *dashboardSpec = [ASStackLayoutSpec stackLayoutSpecWithDirection:ASStackLayoutDirectionHorizontal + spacing:SPACING + justifyContent:ASStackLayoutJustifyContentStart + alignItems:ASStackLayoutAlignItemsStretch + children:@[lonlatConfigSpec, _updateRegionButton]]; + + ASStackLayoutSpec *headerVerticalStack = [ASStackLayoutSpec stackLayoutSpecWithDirection:ASStackLayoutDirectionVertical + spacing:SPACING + justifyContent:ASStackLayoutJustifyContentStart + alignItems:ASStackLayoutAlignItemsStretch + children:@[dashboardSpec, _liveMapToggleButton]]; + + dashboardSpec.style.flexGrow = 1.0; - _mapNode.style.flexGrow = YES; - - ASStackLayoutSpec *lonlatSpec = - [ASStackLayoutSpec - stackLayoutSpecWithDirection:ASStackLayoutDirectionHorizontal - spacing:SPACING - justifyContent:ASStackLayoutJustifyContentStart - alignItems:ASStackLayoutAlignItemsCenter - children:@[_latEditableNode, _lonEditableNode]]; - lonlatSpec.style.flexGrow = true; - - ASStackLayoutSpec *deltaLonlatSpec = - [ASStackLayoutSpec - stackLayoutSpecWithDirection:ASStackLayoutDirectionHorizontal - spacing:SPACING - justifyContent:ASStackLayoutJustifyContentStart - alignItems:ASStackLayoutAlignItemsCenter - children:@[_deltaLatEditableNode, _deltaLonEditableNode]]; - deltaLonlatSpec.style.flexGrow = true; - - ASStackLayoutSpec *lonlatConfigSpec = - [ASStackLayoutSpec - stackLayoutSpecWithDirection:ASStackLayoutDirectionVertical - spacing:SPACING - justifyContent:ASStackLayoutJustifyContentStart - alignItems:ASStackLayoutAlignItemsStretch - children:@[lonlatSpec, deltaLonlatSpec]]; - lonlatConfigSpec.style.flexGrow = true; - - ASStackLayoutSpec *buttonsSpec = - [ASStackLayoutSpec - stackLayoutSpecWithDirection:ASStackLayoutDirectionVertical - spacing:SPACING - justifyContent:ASStackLayoutJustifyContentStart - alignItems:ASStackLayoutAlignItemsStretch - children:@[_updateRegionButton, _liveMapToggleButton]]; - buttonsSpec.style.flexGrow = true; - - ASStackLayoutSpec *dashboardSpec = - [ASStackLayoutSpec - stackLayoutSpecWithDirection:ASStackLayoutDirectionHorizontal - spacing:SPACING - justifyContent:ASStackLayoutJustifyContentStart - alignItems:ASStackLayoutAlignItemsStretch - children:@[lonlatConfigSpec, buttonsSpec]]; - dashboardSpec.style.flexGrow = true; - - ASInsetLayoutSpec *insetSpec = - [ASInsetLayoutSpec - insetLayoutSpecWithInsets:UIEdgeInsetsMake(20, 10, 0, 10) - child:dashboardSpec]; - - ASStackLayoutSpec *layoutSpec = - [ASStackLayoutSpec - stackLayoutSpecWithDirection:ASStackLayoutDirectionVertical - spacing:SPACING - justifyContent:ASStackLayoutJustifyContentStart - alignItems:ASStackLayoutAlignItemsStretch - children:@[insetSpec, _mapNode ]]; + ASInsetLayoutSpec *insetSpec = [ASInsetLayoutSpec insetLayoutSpecWithInsets:UIEdgeInsetsMake(40, 10, 0, 10) + child:headerVerticalStack]; + + ASStackLayoutSpec *layoutSpec = [ASStackLayoutSpec stackLayoutSpecWithDirection:ASStackLayoutDirectionVertical + spacing:SPACING + justifyContent:ASStackLayoutJustifyContentStart + alignItems:ASStackLayoutAlignItemsStretch + children:@[insetSpec, _mapNode]]; + return layoutSpec; } -#pragma mark - Button actions +#pragma mark - Button Actions - (void)updateRegion { @@ -204,7 +203,8 @@ double const deltaLat = [f numberFromString:_deltaLatEditableNode.attributedText.string].doubleValue; double const deltaLon = [f numberFromString:_deltaLonEditableNode.attributedText.string].doubleValue; - MKCoordinateRegion region = MKCoordinateRegionMake(CLLocationCoordinate2DMake(lat, lon), + // TODO: check for valid latitude / longitude coordinates + MKCoordinateRegion region = MKCoordinateRegionMake(CLLocationCoordinate2DMake(lat, lon), MKCoordinateSpanMake(deltaLat, deltaLon)); _mapNode.region = region; @@ -218,17 +218,30 @@ [_liveMapToggleButton setTitle:liveMapStr withFont:[UIFont systemFontOfSize:14] withColor:[UIColor blueColor] forState:ASControlStateHighlighted]; } -#pragma mark - Helpers +- (void)updateLocationTextWithMKCoordinateRegion:(MKCoordinateRegion)region +{ + _latEditableNode.attributedText = [self attributedStringFromFloat:region.center.latitude]; + _lonEditableNode.attributedText = [self attributedStringFromFloat:region.center.longitude]; + _deltaLatEditableNode.attributedText = [self attributedStringFromFloat:region.span.latitudeDelta]; + _deltaLonEditableNode.attributedText = [self attributedStringFromFloat:region.span.longitudeDelta]; +} + +#pragma mark - Helper Methods + +- (NSAttributedString *)attributedStringFromFloat:(CGFloat)value +{ + return [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"%0.3f", value]]; +} - (void)addAnnotations { MKPointAnnotation *brno = [MKPointAnnotation new]; brno.coordinate = CLLocationCoordinate2DMake(49.2002211, 16.6078411); - brno.title = @"Brno city"; + brno.title = @"Brno City"; CustomMapAnnotation *atlantic = [CustomMapAnnotation new]; atlantic.coordinate = CLLocationCoordinate2DMake(38.6442228, -29.9956942); - atlantic.title = @"Atlantic ocean"; + atlantic.title = @"Atlantic Ocean"; atlantic.image = [UIImage imageNamed:@"Water"]; CustomMapAnnotation *kilimanjaro = [CustomMapAnnotation new]; @@ -299,6 +312,7 @@ - (MKAnnotationView *)annotationViewForAnnotation:(id)annotation { MKAnnotationView *av; + if ([annotation isKindOfClass:[CustomMapAnnotation class]]) { av = [[MKAnnotationView alloc] init]; av.centerOffset = CGPointMake(21, 21); @@ -306,18 +320,17 @@ } else { av = [[MKPinAnnotationView alloc] initWithAnnotation:nil reuseIdentifier:@""]; } - + av.opaque = NO; + return av; } #pragma mark - MKMapViewDelegate -- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated { - _latEditableNode.attributedText = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"%f", mapView.region.center.latitude]]; - _lonEditableNode.attributedText = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"%f", mapView.region.center.longitude]]; - _deltaLatEditableNode.attributedText = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"%f", mapView.region.span.latitudeDelta]]; - _deltaLonEditableNode.attributedText = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"%f", mapView.region.span.longitudeDelta]]; +- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated +{ + [self updateLocationTextWithMKCoordinateRegion:mapView.region]; } - (MKAnnotationView *)mapView:(MKMapView *)__unused mapView viewForAnnotation:(id)annotation diff --git a/examples/ASMapNode/Sample/ViewController.m b/examples/ASMapNode/Sample/ViewController.m index 53967e2035..4dc690ae34 100644 --- a/examples/ASMapNode/Sample/ViewController.m +++ b/examples/ASMapNode/Sample/ViewController.m @@ -36,18 +36,11 @@ return self; } -#pragma mark - UIViewController - -- (void)viewDidLoad -{ - [super viewDidLoad]; - -} - - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; - self.navigationController.navigationBarHidden = true; + + self.navigationController.navigationBarHidden = YES; } @end From 0dd170dde4ac7993f94f9acfb6b99882c4e3f315 Mon Sep 17 00:00:00 2001 From: Hannah Troisi Date: Thu, 20 Oct 2016 17:10:20 -0700 Subject: [PATCH 23/59] clean up ASCollectionView example project (#2384) --- examples/ASCollectionView/Sample/ItemNode.m | 4 ++++ .../Sample/PresentingViewController.m | 5 +++- .../Sample/SupplementaryNode.m | 3 +++ .../ASCollectionView/Sample/ViewController.m | 24 +++++++++++-------- 4 files changed, 25 insertions(+), 11 deletions(-) diff --git a/examples/ASCollectionView/Sample/ItemNode.m b/examples/ASCollectionView/Sample/ItemNode.m index fedd2ca9d5..2f61c4ff46 100644 --- a/examples/ASCollectionView/Sample/ItemNode.m +++ b/examples/ASCollectionView/Sample/ItemNode.m @@ -22,10 +22,12 @@ - (instancetype)initWithString:(NSString *)string { self = [super init]; + if (self != nil) { self.text = string; [self updateBackgroundColor]; } + return self; } @@ -43,12 +45,14 @@ - (void)setSelected:(BOOL)selected { [super setSelected:selected]; + [self updateBackgroundColor]; } - (void)setHighlighted:(BOOL)highlighted { [super setHighlighted:highlighted]; + [self updateBackgroundColor]; } diff --git a/examples/ASCollectionView/Sample/PresentingViewController.m b/examples/ASCollectionView/Sample/PresentingViewController.m index f191898d82..38a34fc357 100644 --- a/examples/ASCollectionView/Sample/PresentingViewController.m +++ b/examples/ASCollectionView/Sample/PresentingViewController.m @@ -30,7 +30,10 @@ { [super viewDidLoad]; - self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Push Details" style:UIBarButtonItemStylePlain target:self action:@selector(pushNewViewController)]; + self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Push Details" + style:UIBarButtonItemStylePlain + target:self + action:@selector(pushNewViewController)]; } - (void)pushNewViewController diff --git a/examples/ASCollectionView/Sample/SupplementaryNode.m b/examples/ASCollectionView/Sample/SupplementaryNode.m index af5977711f..b1b1b905c9 100644 --- a/examples/ASCollectionView/Sample/SupplementaryNode.m +++ b/examples/ASCollectionView/Sample/SupplementaryNode.m @@ -32,12 +32,14 @@ static CGFloat kInsets = 15.0; - (instancetype)initWithText:(NSString *)text { self = [super init]; + if (self != nil) { _textNode = [[ASTextNode alloc] init]; _textNode.attributedText = [[NSAttributedString alloc] initWithString:text attributes:[self textAttributes]]; [self addSubnode:_textNode]; } + return self; } @@ -47,6 +49,7 @@ static CGFloat kInsets = 15.0; center.centeringOptions = ASCenterLayoutSpecCenteringXY; center.child = self.textNode; UIEdgeInsets insets = UIEdgeInsetsMake(kInsets, kInsets, kInsets, kInsets); + return [ASInsetLayoutSpec insetLayoutSpecWithInsets:insets child:center]; } diff --git a/examples/ASCollectionView/Sample/ViewController.m b/examples/ASCollectionView/Sample/ViewController.m index 302cbf6127..56a1d510ec 100644 --- a/examples/ASCollectionView/Sample/ViewController.m +++ b/examples/ASCollectionView/Sample/ViewController.m @@ -21,18 +21,17 @@ #import "SupplementaryNode.h" #import "ItemNode.h" -@interface ViewController () -@property (nonatomic, strong) ASCollectionView *collectionView; -@property (nonatomic, strong) NSArray *data; -@end - @interface ViewController () +@property (nonatomic, strong) ASCollectionView *collectionView; +@property (nonatomic, strong) NSArray *data; + @end - @implementation ViewController +#pragma mark - Lifecycle + - (void)dealloc { self.collectionView.asyncDataSource = nil; @@ -52,20 +51,24 @@ // This method is deprecated because we reccommend using ASCollectionNode instead of ASCollectionView. // This functionality & example project remains for users who insist on using ASCollectionView. self.collectionView = [[ASCollectionView alloc] initWithFrame:self.view.bounds collectionViewLayout:layout]; - self.collectionView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; self.collectionView.asyncDataSource = self; self.collectionView.asyncDelegate = self; + + self.collectionView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; self.collectionView.backgroundColor = [UIColor whiteColor]; // This method is deprecated because we reccommend using ASCollectionNode instead of ASCollectionView. // This functionality & example project remains for users who insist on using ASCollectionView. [self.collectionView registerSupplementaryNodeOfKind:UICollectionElementKindSectionHeader]; [self.collectionView registerSupplementaryNodeOfKind:UICollectionElementKindSectionFooter]; + [self.view addSubview:self.collectionView]; #if !SIMULATE_WEB_RESPONSE self.navigationItem.leftItemsSupplementBackButton = YES; - self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh target:self action:@selector(reloadTapped)]; + self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh + target:self + action:@selector(reloadTapped)]; #endif #if SIMULATE_WEB_RESPONSE @@ -94,6 +97,8 @@ #endif } +#pragma mark - Button Actions + - (void)reloadTapped { // This method is deprecated because we reccommend using ASCollectionNode instead of ASCollectionView. @@ -101,8 +106,7 @@ [self.collectionView reloadData]; } -#pragma mark - -#pragma mark ASCollectionView data source. +#pragma mark - ASCollectionView Data Source - (ASCellNodeBlock)collectionView:(ASCollectionView *)collectionView nodeBlockForItemAtIndexPath:(NSIndexPath *)indexPath; { From 9719357901cb656192924208fb61cffd7a322b17 Mon Sep 17 00:00:00 2001 From: Hannah Troisi Date: Thu, 20 Oct 2016 17:27:31 -0700 Subject: [PATCH 24/59] [ASLayoutElement] Move ASDisplayNode's .name property to ASLayoutElement (renamed to .debugName) (#2395) * Move ASDisplay .name property to ASLayoutElement * keep ASDisplayNode.name deprecated * address @appleguy's comments --- AsyncDisplayKit/ASDisplayNode+Deprecated.h | 8 ++++ AsyncDisplayKit/ASDisplayNode.h | 7 --- AsyncDisplayKit/ASDisplayNode.mm | 38 +++++++++++----- AsyncDisplayKit/Layout/ASLayoutElement.h | 5 +++ AsyncDisplayKit/Layout/ASLayoutSpec.mm | 24 +++++++++- AsyncDisplayKitTests/ASCollectionViewTests.mm | 4 +- .../ASDisplayNodeAppearanceTests.m | 4 +- .../ASDisplayNodeImplicitHierarchyTests.m | 2 +- AsyncDisplayKitTests/ASDisplayNodeTests.m | 44 +++++++++---------- 9 files changed, 88 insertions(+), 48 deletions(-) diff --git a/AsyncDisplayKit/ASDisplayNode+Deprecated.h b/AsyncDisplayKit/ASDisplayNode+Deprecated.h index 2ec26b7b2b..563766610c 100644 --- a/AsyncDisplayKit/ASDisplayNode+Deprecated.h +++ b/AsyncDisplayKit/ASDisplayNode+Deprecated.h @@ -14,6 +14,14 @@ @interface ASDisplayNode (Deprecated) +/** + * @abstract The name of this node, which will be displayed in `description`. The default value is nil. + * + * @deprecated Deprecated in version 2.0: Use .debugName instead. This value will display in + * results of the -asciiArtString method (@see ASLayoutElementAsciiArtProtocol). + */ +@property (nullable, nonatomic, copy) NSString *name ASDISPLAYNODE_DEPRECATED_MSG("Use .debugName instead."); + /** * @abstract Asks the node to measure and return the size that best fits its subnodes. * diff --git a/AsyncDisplayKit/ASDisplayNode.h b/AsyncDisplayKit/ASDisplayNode.h index 1c65546d89..89a4942e04 100644 --- a/AsyncDisplayKit/ASDisplayNode.h +++ b/AsyncDisplayKit/ASDisplayNode.h @@ -173,13 +173,6 @@ extern NSInteger const ASDefaultDrawingPriority; */ - (void)onDidLoad:(ASDisplayNodeDidLoadBlock)body; -/** @name Properties */ - -/** - * @abstract The name of this node, which will be displayed in `description`. The default value is nil. - */ -@property (nullable, nonatomic, copy) NSString *name; - /** * @abstract Returns whether the node is synchronous. * diff --git a/AsyncDisplayKit/ASDisplayNode.mm b/AsyncDisplayKit/ASDisplayNode.mm index 0bcf8afdb5..f775504091 100644 --- a/AsyncDisplayKit/ASDisplayNode.mm +++ b/AsyncDisplayKit/ASDisplayNode.mm @@ -77,7 +77,7 @@ NSString * const ASRenderingEngineDidDisplayNodesScheduledBeforeTimestamp = @"AS @dynamic layoutElementType; -@synthesize name = _name; +@synthesize debugName = _debugName; @synthesize isFinalLayoutElement = _isFinalLayoutElement; @synthesize threadSafeBounds = _threadSafeBounds; @synthesize layoutSpecBlock = _layoutSpecBlock; @@ -677,17 +677,17 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c) return (_view != nil || (_layer != nil && _flags.layerBacked)); } -- (NSString *)name +- (NSString *)debugName { ASDN::MutexLocker l(__instanceLock__); - return _name; + return _debugName; } -- (void)setName:(NSString *)name +- (void)setDebugName:(NSString *)debugName { ASDN::MutexLocker l(__instanceLock__); - if (!ASObjectIsEqual(_name, name)) { - _name = [name copy]; + if (!ASObjectIsEqual(_debugName, debugName)) { + _debugName = [debugName copy]; } } @@ -3299,8 +3299,8 @@ static const char *ASDisplayNodeDrawingPriorityKey = "ASDrawingPriority"; - (NSMutableArray *)propertiesForDescription { NSMutableArray *result = [NSMutableArray array]; - if (self.name.length > 0) { - [result addObject:@{ @"name" : ASStringWithQuotesIfMultiword(self.name) }]; + if (self.debugName.length > 0) { + [result addObject:@{ @"debugName" : ASStringWithQuotesIfMultiword(self.debugName) }]; } return result; } @@ -3309,8 +3309,8 @@ static const char *ASDisplayNodeDrawingPriorityKey = "ASDrawingPriority"; { NSMutableArray *result = [NSMutableArray array]; - if (self.name.length > 0) { - [result addObject:@{ @"name" : ASStringWithQuotesIfMultiword(self.name)}]; + if (self.debugName.length > 0) { + [result addObject:@{ @"debugName" : ASStringWithQuotesIfMultiword(self.debugName)}]; } CGRect windowFrame = [self _frameInWindow]; @@ -3488,6 +3488,16 @@ ASEnvironmentLayoutExtensibilityForwarding #pragma mark - Deprecated +- (NSString *)name +{ + return self.debugName; +} + +- (void)setName:(NSString *)name +{ + self.debugName = name; +} + - (CGSize)measure:(CGSize)constrainedSize { return [self layoutThatFits:ASSizeRangeMake(CGSizeZero, constrainedSize)].size; @@ -3551,12 +3561,16 @@ ASEnvironmentLayoutExtensibilityForwarding - (NSString *)asciiArtString { - return [ASLayoutSpec asciiArtStringForChildren:@[] parentName:[self asciiArtName]]; + return [ASLayoutSpec asciiArtStringForChildren:@[] parentName:[self asciiArtName]]; } - (NSString *)asciiArtName { - return NSStringFromClass([self class]); + NSString *string = NSStringFromClass([self class]); + if (_debugName) { + string = [string stringByAppendingString:[NSString stringWithFormat:@"\"%@\"",_debugName]]; + } + return string; } @end diff --git a/AsyncDisplayKit/Layout/ASLayoutElement.h b/AsyncDisplayKit/Layout/ASLayoutElement.h index 0f22d2c343..fcfd99a10f 100644 --- a/AsyncDisplayKit/Layout/ASLayoutElement.h +++ b/AsyncDisplayKit/Layout/ASLayoutElement.h @@ -69,6 +69,11 @@ NS_ASSUME_NONNULL_BEGIN */ @property (nonatomic, assign, readonly) ASLayoutElementStyle *style; +/** + * @abstract Optional name that is printed by ascii art string and displayed in description. + */ +@property (nullable, nonatomic, copy) NSString *debugName; + #pragma mark - Calculate layout diff --git a/AsyncDisplayKit/Layout/ASLayoutSpec.mm b/AsyncDisplayKit/Layout/ASLayoutSpec.mm index f7d5bd77f9..d1dc4126bc 100644 --- a/AsyncDisplayKit/Layout/ASLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASLayoutSpec.mm @@ -18,6 +18,7 @@ // Dynamic properties for ASLayoutElements @dynamic layoutElementType; +@synthesize debugName = _debugName; @synthesize isFinalLayoutElement = _isFinalLayoutElement; #pragma mark - Class @@ -276,6 +277,22 @@ ASEnvironmentLayoutExtensibilityForwarding } } +#pragma mark - Debugging + +- (NSString *)debugName +{ + ASDN::MutexLocker l(__instanceLock__); + return _debugName; +} + +- (void)setDebugName:(NSString *)debugName +{ + ASDN::MutexLocker l(__instanceLock__); + if (!ASObjectIsEqual(_debugName, debugName)) { + _debugName = [debugName copy]; + } +} + @end #pragma mark - ASWrapperLayoutSpec @@ -305,7 +322,6 @@ ASEnvironmentLayoutExtensibilityForwarding @end - #pragma mark - ASLayoutSpec (Debugging) @implementation ASLayoutSpec (Debugging) @@ -340,7 +356,11 @@ ASEnvironmentLayoutExtensibilityForwarding - (NSString *)asciiArtName { - return NSStringFromClass([self class]); + NSString *string = NSStringFromClass([self class]); + if (_debugName) { + string = [string stringByAppendingString:[NSString stringWithFormat:@" (debugName = %@)",_debugName]]; + } + return string; } @end diff --git a/AsyncDisplayKitTests/ASCollectionViewTests.mm b/AsyncDisplayKitTests/ASCollectionViewTests.mm index 555588a394..d8940b2b53 100644 --- a/AsyncDisplayKitTests/ASCollectionViewTests.mm +++ b/AsyncDisplayKitTests/ASCollectionViewTests.mm @@ -462,12 +462,12 @@ [[[dataSource stub] andDo:^(NSInvocation *invocation) { __autoreleasing ASCellNode *suppNode = [[ASCellNode alloc] init]; int thisNodeIdx = nodeIdx++; - suppNode.name = [NSString stringWithFormat:@"Cell #%d", thisNodeIdx]; + suppNode.debugName = [NSString stringWithFormat:@"Cell #%d", thisNodeIdx]; [keepaliveNodes addObject:suppNode]; ASDisplayNode *layerBacked = [[ASDisplayNode alloc] init]; layerBacked.layerBacked = YES; - layerBacked.name = [NSString stringWithFormat:@"Subnode #%d", thisNodeIdx]; + layerBacked.debugName = [NSString stringWithFormat:@"Subnode #%d", thisNodeIdx]; [suppNode addSubnode:layerBacked]; [invocation setReturnValue:&suppNode]; }] collectionNode:cn nodeForSupplementaryElementOfKind:UICollectionElementKindSectionHeader atIndexPath:OCMOCK_ANY]; diff --git a/AsyncDisplayKitTests/ASDisplayNodeAppearanceTests.m b/AsyncDisplayKitTests/ASDisplayNodeAppearanceTests.m index 7d8c3f6d2a..7b629e129c 100644 --- a/AsyncDisplayKitTests/ASDisplayNodeAppearanceTests.m +++ b/AsyncDisplayKitTests/ASDisplayNodeAppearanceTests.m @@ -55,10 +55,10 @@ static dispatch_block_t modifyMethodByAddingPrologueBlockAndReturnCleanupBlock(C @end // Conveniences for making nodes named a certain way -#define DeclareNodeNamed(n) ASDisplayNode *n = [[ASDisplayNode alloc] init]; n.name = @#n +#define DeclareNodeNamed(n) ASDisplayNode *n = [[ASDisplayNode alloc] init]; n.debugName = @#n #define DeclareViewNamed(v) \ ASDisplayNode *node_##v = [[ASDisplayNode alloc] init]; \ - node_##v.name = @#v; \ + node_##v.debugName = @#v; \ UIView *v = node_##v.view; @implementation ASDisplayNodeAppearanceTests diff --git a/AsyncDisplayKitTests/ASDisplayNodeImplicitHierarchyTests.m b/AsyncDisplayKitTests/ASDisplayNodeImplicitHierarchyTests.m index 356de3ad87..6944e676e5 100644 --- a/AsyncDisplayKitTests/ASDisplayNodeImplicitHierarchyTests.m +++ b/AsyncDisplayKitTests/ASDisplayNodeImplicitHierarchyTests.m @@ -121,7 +121,7 @@ - (void)testLayoutTransitionWillThrowForManualSubnodeManagement { ASDisplayNode *node1 = [[ASDisplayNode alloc] init]; - node1.name = @"node1"; + node1.debugName = @"node1"; ASSpecTestDisplayNode *node = [[ASSpecTestDisplayNode alloc] init]; node.automaticallyManagesSubnodes = YES; diff --git a/AsyncDisplayKitTests/ASDisplayNodeTests.m b/AsyncDisplayKitTests/ASDisplayNodeTests.m index d325450018..47fed66bba 100644 --- a/AsyncDisplayKitTests/ASDisplayNodeTests.m +++ b/AsyncDisplayKitTests/ASDisplayNodeTests.m @@ -25,27 +25,27 @@ #import "ASInsetLayoutSpec.h" // Conveniences for making nodes named a certain way -#define DeclareNodeNamed(n) ASDisplayNode *n = [[ASDisplayNode alloc] init]; n.name = @#n +#define DeclareNodeNamed(n) ASDisplayNode *n = [[ASDisplayNode alloc] init]; n.debugName = @#n #define DeclareViewNamed(v) \ ASDisplayNode *node_##v = [[ASDisplayNode alloc] init]; \ - node_##v.name = @#v; \ + node_##v.debugName = @#v; \ UIView *v = node_##v.view; #define DeclareLayerNamed(l) \ ASDisplayNode *node_##l = [[ASDisplayNode alloc] init]; \ - node_##l.name = @#l; \ + node_##l.debugName = @#l; \ node_##l.layerBacked = YES; \ CALayer *l = node_##l.layer; static NSString *orderStringFromSublayers(CALayer *l) { - return [[[l.sublayers valueForKey:@"asyncdisplaykit_node"] valueForKey:@"name"] componentsJoinedByString:@","]; + return [[[l.sublayers valueForKey:@"asyncdisplaykit_node"] valueForKey:@"debugName"] componentsJoinedByString:@","]; } static NSString *orderStringFromSubviews(UIView *v) { - return [[[v.subviews valueForKey:@"asyncdisplaykit_node"] valueForKey:@"name"] componentsJoinedByString:@","]; + return [[[v.subviews valueForKey:@"asyncdisplaykit_node"] valueForKey:@"debugName"] componentsJoinedByString:@","]; } static NSString *orderStringFromSubnodes(ASDisplayNode *n) { - return [[n.subnodes valueForKey:@"name"] componentsJoinedByString:@","]; + return [[n.subnodes valueForKey:@"debugName"] componentsJoinedByString:@","]; } // Asserts subnode, subview, sublayer order match what you provide here @@ -60,17 +60,17 @@ if (loaded) {\ #define XCTAssertNodesHaveParent(parent, nodes ...) \ for (ASDisplayNode *n in @[ nodes ]) {\ - XCTAssertEqualObjects(parent, n.supernode, @"%@ has the wrong parent", n.name);\ + XCTAssertEqualObjects(parent, n.supernode, @"%@ has the wrong parent", n.debugName);\ } #define XCTAssertNodesLoaded(nodes ...) \ for (ASDisplayNode *n in @[ nodes ]) {\ - XCTAssertTrue(n.nodeLoaded, @"%@ should be loaded", n.name);\ + XCTAssertTrue(n.nodeLoaded, @"%@ should be loaded", n.debugName);\ } #define XCTAssertNodesNotLoaded(nodes ...) \ for (ASDisplayNode *n in @[ nodes ]) {\ - XCTAssertFalse(n.nodeLoaded, @"%@ should not be loaded", n.name);\ + XCTAssertFalse(n.nodeLoaded, @"%@ should not be loaded", n.debugName);\ } @@ -330,7 +330,7 @@ for (ASDisplayNode *n in @[ nodes ]) {\ XCTAssertEqual(NO, node.displaySuspended, @"default displaySuspended broken %@", hasLoadedView); XCTAssertEqual(YES, node.displaysAsynchronously, @"default displaysAsynchronously broken %@", hasLoadedView); XCTAssertEqual(NO, node.asyncdisplaykit_asyncTransactionContainer, @"default asyncdisplaykit_asyncTransactionContainer broken %@", hasLoadedView); - XCTAssertEqualObjects(nil, node.name, @"default name broken %@", hasLoadedView); + XCTAssertEqualObjects(nil, node.debugName, @"default name broken %@", hasLoadedView); XCTAssertEqual(NO, node.isAccessibilityElement, @"default isAccessibilityElement is broken %@", hasLoadedView); XCTAssertEqual((id)nil, node.accessibilityLabel, @"default accessibilityLabel is broken %@", hasLoadedView); @@ -428,7 +428,7 @@ for (ASDisplayNode *n in @[ nodes ]) {\ XCTAssertEqual(YES, node.asyncdisplaykit_asyncTransactionContainer, @"asyncTransactionContainer broken %@", hasLoadedView); XCTAssertEqual(NO, node.userInteractionEnabled, @"userInteractionEnabled broken %@", hasLoadedView); XCTAssertEqual((BOOL)!isLayerBacked, node.exclusiveTouch, @"exclusiveTouch broken %@", hasLoadedView); - XCTAssertEqualObjects(@"quack like a duck", node.name, @"name broken %@", hasLoadedView); + XCTAssertEqualObjects(@"quack like a duck", node.debugName, @"debugName broken %@", hasLoadedView); XCTAssertEqual(YES, node.isAccessibilityElement, @"accessibilityElement broken %@", hasLoadedView); XCTAssertEqualObjects(@"Ship love", node.accessibilityLabel, @"accessibilityLabel broken %@", hasLoadedView); @@ -486,7 +486,7 @@ for (ASDisplayNode *n in @[ nodes ]) {\ node.displaysAsynchronously = NO; node.asyncdisplaykit_asyncTransactionContainer = YES; node.userInteractionEnabled = NO; - node.name = @"quack like a duck"; + node.debugName = @"quack like a duck"; node.isAccessibilityElement = YES; node.accessibilityLabel = @"Ship love"; @@ -1851,14 +1851,14 @@ static bool stringContainsPointer(NSString *description, id p) { ASDisplayNode *node = [[ASDisplayNode alloc] init]; node.layerBacked = isLayerBacked; - XCTAssertFalse([node.description rangeOfString:@"name"].location != NSNotFound, @"Shouldn't reference 'name' in description"); - node.name = @"big troll eater name"; + XCTAssertFalse([node.description rangeOfString:@"debugName"].location != NSNotFound, @"Shouldn't reference 'debugName' in description"); + node.debugName = @"big troll eater name"; - XCTAssertTrue([node.description rangeOfString:node.name].location != NSNotFound, @"Name didn't end up in description"); - XCTAssertTrue([node.description rangeOfString:@"name"].location != NSNotFound, @"Shouldn't reference 'name' in description"); + XCTAssertFalse([node.description rangeOfString:node.debugName].location == NSNotFound, @"debugName didn't end up in description"); + XCTAssertFalse([node.description rangeOfString:@"debugName"].location == NSNotFound, @"Shouldn't reference 'debugName' in description"); [node layer]; - XCTAssertTrue([node.description rangeOfString:node.name].location != NSNotFound, @"Name didn't end up in description"); - XCTAssertTrue([node.description rangeOfString:@"name"].location != NSNotFound, @"Shouldn't reference 'name' in description"); + XCTAssertFalse([node.description rangeOfString:node.debugName].location == NSNotFound, @"debugName didn't end up in description"); + XCTAssertFalse([node.description rangeOfString:@"debugName"].location == NSNotFound, @"Shouldn't reference 'debugName' in description"); } - (void)testNameInDescriptionLayer @@ -1986,12 +1986,12 @@ static bool stringContainsPointer(NSString *description, id p) { { NS_VALID_UNTIL_END_OF_SCOPE ASDisplayNode *node = [[ASDisplayNode alloc] init]; nodeView = node.view; - node.name = @"Node"; + node.debugName = @"Node"; NS_VALID_UNTIL_END_OF_SCOPE ASDisplayNode *subnode = [[ASDisplayNode alloc] init]; subnode.layerBacked = YES; [node addSubnode:subnode]; - subnode.name = @"Subnode"; + subnode.debugName = @"Subnode"; [window addSubview:nodeView]; } @@ -2023,11 +2023,11 @@ static bool stringContainsPointer(NSString *description, id p) { - (void)testThatSubnodeGetsInterfaceStateSetIfRasterized { ASTestDisplayNode *node = [[ASTestDisplayNode alloc] init]; - node.name = @"Node"; + node.debugName = @"Node"; node.shouldRasterizeDescendants = YES; ASTestDisplayNode *subnode = [[ASTestDisplayNode alloc] init]; - subnode.name = @"Subnode"; + subnode.debugName = @"Subnode"; [node addSubnode:subnode]; [node view]; // Node needs to be loaded From 15aa784fe829666f0b31e29a9439c0eceb620093 Mon Sep 17 00:00:00 2001 From: Hannah Troisi Date: Fri, 21 Oct 2016 10:19:27 -0700 Subject: [PATCH 25/59] [ASCollectionNode] add -indexPathsForVisibleNodes (#2451) --- AsyncDisplayKit/ASCollectionNode.h | 6 ++++++ AsyncDisplayKit/ASCollectionNode.mm | 13 +++++++++++++ 2 files changed, 19 insertions(+) diff --git a/AsyncDisplayKit/ASCollectionNode.h b/AsyncDisplayKit/ASCollectionNode.h index ab4c06ce03..b36d94ee88 100644 --- a/AsyncDisplayKit/ASCollectionNode.h +++ b/AsyncDisplayKit/ASCollectionNode.h @@ -313,6 +313,12 @@ NS_ASSUME_NONNULL_BEGIN */ - (nullable NSIndexPath *)indexPathForNode:(ASCellNode *)cellNode AS_WARN_UNUSED_RESULT; +/** + * Retrieve the index paths of all visible items. + * + * @return an array containing the index paths of all visible items. This must be called on the main thread. + */ +- (NSArray<__kindof NSIndexPath *> *)indexPathsForVisibleItems AS_WARN_UNUSED_RESULT; /** * Retrieves the context object for the given section, as provided by the data source in diff --git a/AsyncDisplayKit/ASCollectionNode.mm b/AsyncDisplayKit/ASCollectionNode.mm index 07d2c8c5a4..ab6123be31 100644 --- a/AsyncDisplayKit/ASCollectionNode.mm +++ b/AsyncDisplayKit/ASCollectionNode.mm @@ -295,6 +295,19 @@ return [self.dataController indexPathForNode:cellNode]; } +- (NSArray<__kindof NSIndexPath *> *)indexPathsForVisibleItems +{ + NSMutableArray *indexPathsArray = [NSMutableArray new]; + for (ASCellNode *cell in [self visibleNodes]) { + NSIndexPath *indexPath = [self indexPathForNode:cell]; + if (indexPath) { + [indexPathsArray addObject:indexPath]; + } + } + return indexPathsArray; +} + + - (ASCellNode *)nodeForItemAtIndexPath:(NSIndexPath *)indexPath { return [self.dataController nodeAtIndexPath:indexPath]; From 3a2ca70676774ce4156f00188e37fc5bcc4a5637 Mon Sep 17 00:00:00 2001 From: Scott Goodson Date: Fri, 21 Oct 2016 11:21:21 -0700 Subject: [PATCH 26/59] [ASDisplayNode] Simplify / shorten temporary bridged implementation of preferredFrameSize. --- AsyncDisplayKit/ASDisplayNode.mm | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/AsyncDisplayKit/ASDisplayNode.mm b/AsyncDisplayKit/ASDisplayNode.mm index f775504091..9b132030fc 100644 --- a/AsyncDisplayKit/ASDisplayNode.mm +++ b/AsyncDisplayKit/ASDisplayNode.mm @@ -3510,8 +3510,6 @@ ASEnvironmentLayoutExtensibilityForwarding - (void)setPreferredFrameSize:(CGSize)preferredFrameSize { - ASDN::MutexLocker l(__instanceLock__); - // Deprecated preferredFrameSize just calls through to set width and height self.style.preferredSize = preferredFrameSize; [self invalidateCalculatedLayout]; @@ -3519,14 +3517,9 @@ ASEnvironmentLayoutExtensibilityForwarding - (CGSize)preferredFrameSize { - ASDN::MutexLocker l(__instanceLock__); - - ASLayoutElementStyle *style = self.style; - if (style.width.unit == ASDimensionUnitPoints && style.height.unit == ASDimensionUnitPoints) { - return CGSizeMake(style.width.value, style.height.value); - } - - return CGSizeZero; + ASLayoutSize size = self.style.preferredLayoutSize; + BOOL isPoints = (size.width.unit == ASDimensionUnitPoints && size.height.unit == ASDimensionUnitPoints); + return isPoints ? CGSizeMake(size.width.value, size.height.value) : CGSizeZero; } @end From e87ac541387c4b99321a74168e5ba6177366176c Mon Sep 17 00:00:00 2001 From: Hannah Troisi Date: Fri, 21 Oct 2016 12:43:51 -0700 Subject: [PATCH 27/59] disable flaky table thrash test (#2458) --- AsyncDisplayKitTests/ASTableViewTests.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AsyncDisplayKitTests/ASTableViewTests.m b/AsyncDisplayKitTests/ASTableViewTests.m index f57e1d0220..2b2b480aef 100644 --- a/AsyncDisplayKitTests/ASTableViewTests.m +++ b/AsyncDisplayKitTests/ASTableViewTests.m @@ -256,7 +256,7 @@ return indexPaths; } -- (void)testReloadData +- (void)DISABLED_testReloadData { // Keep the viewport moderately sized so that new cells are loaded on scrolling ASTableView *tableView = [[ASTestTableView alloc] __initWithFrame:CGRectMake(0, 0, 100, 500) From 2c6f8b0506f7a144955eeb4cc1f36fa747b59ac4 Mon Sep 17 00:00:00 2001 From: appleguy Date: Fri, 21 Oct 2016 13:12:13 -0700 Subject: [PATCH 28/59] [AsyncDisplayKit 2] Final changes to ease migration of clients to 2.0 APIs. (#2460) --- AsyncDisplayKit.podspec | 3 +- AsyncDisplayKit/ASDisplayNode.h | 24 ++++ AsyncDisplayKit/ASDisplayNode.mm | 92 +++++++------- .../Layout/ASAbsoluteLayoutElement.h | 5 + AsyncDisplayKit/Layout/ASAbsoluteLayoutSpec.h | 9 ++ .../Layout/ASAbsoluteLayoutSpec.mm | 29 ++++- AsyncDisplayKit/Layout/ASDimension.h | 71 +++++++++++ AsyncDisplayKit/Layout/ASDimension.mm | 79 ++++++++++++ AsyncDisplayKit/Layout/ASLayout.h | 17 +++ AsyncDisplayKit/Layout/ASLayout.mm | 24 ++++ AsyncDisplayKit/Layout/ASLayoutElement.h | 4 +- AsyncDisplayKit/Layout/ASLayoutElement.mm | 18 +++ .../Layout/ASLayoutElementPrivate.h | 119 ++++++++++++++++++ AsyncDisplayKit/Layout/ASLayoutSpec.h | 2 +- AsyncDisplayKit/Layout/ASLayoutSpec.mm | 15 ++- .../ASDisplayNodeImplicitHierarchyTests.m | 29 ++--- Base/ASBaseDefines.h | 2 +- 17 files changed, 470 insertions(+), 72 deletions(-) diff --git a/AsyncDisplayKit.podspec b/AsyncDisplayKit.podspec index f5dba4322d..9e146ed38d 100644 --- a/AsyncDisplayKit.podspec +++ b/AsyncDisplayKit.podspec @@ -59,7 +59,8 @@ Pod::Spec.new do |spec| spec.subspec 'PINRemoteImage' do |pin| pin.xcconfig = { 'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) PIN_REMOTE_IMAGE=1' } - pin.dependency 'PINRemoteImage/iOS', '= 3.0.0-beta.5' + pin.dependency 'PINRemoteImage/iOS', '>= 3.0.0-beta.4' + pin.dependency 'PINRemoteImage/PINCache' pin.dependency 'AsyncDisplayKit/Core' end diff --git a/AsyncDisplayKit/ASDisplayNode.h b/AsyncDisplayKit/ASDisplayNode.h index 89a4942e04..73639dca9e 100644 --- a/AsyncDisplayKit/ASDisplayNode.h +++ b/AsyncDisplayKit/ASDisplayNode.h @@ -812,9 +812,33 @@ extern NSInteger const ASDefaultDrawingPriority; */ - (void)cancelLayoutTransition; +@end + +@interface ASDisplayNode (Deprecated) #pragma mark - Deprecated +/** + * @abstract Asks the node to measure and return the size that best fits its subnodes. + * + * @param constrainedSize The maximum size the receiver should fit in. + * + * @return A new size that fits the receiver's subviews. + * + * @discussion Though this method does not set the bounds of the view, it does have side effects--caching both the + * constraint and the result. + * + * @warning Subclasses must not override this; it calls -measureWithSizeRange: with zero min size. + * -measureWithSizeRange: caches results from -calculateLayoutThatFits:. Calling this method may + * be expensive if result is not cached. + * + * @see measureWithSizeRange: + * @see [ASDisplayNode(Subclassing) calculateLayoutThatFits:] + * + * @deprecated Deprecated in version 2.0: Use layoutThatFits: with a constrained size of (CGSizeZero, constrainedSize) and call size on the returned ASLayout + */ +- (CGSize)measure:(CGSize)constrainedSize ASDISPLAYNODE_DEPRECATED; + /** * @abstract Provides a default intrinsic content size for calculateSizeThatFits:. This is useful when laying out * a node that either has no intrinsic content size or should be laid out at a different size than its intrinsic content diff --git a/AsyncDisplayKit/ASDisplayNode.mm b/AsyncDisplayKit/ASDisplayNode.mm index 9b132030fc..e6ca7b9269 100644 --- a/AsyncDisplayKit/ASDisplayNode.mm +++ b/AsyncDisplayKit/ASDisplayNode.mm @@ -1654,7 +1654,8 @@ static bool disableNotificationsForMovingBetweenParents(ASDisplayNode *from, ASD - (void)addSubnode:(ASDisplayNode *)subnode { - ASDisplayNodeAssert(self.automaticallyManagesSubnodes == NO, @"Attempt to manually add subnode to node with automaticallyManagesSubnodes=YES. Node: %@", subnode); + // TODO: 2.0 Conversion: Reenable and fix within product code + //ASDisplayNodeAssert(self.automaticallyManagesSubnodes == NO, @"Attempt to manually add subnode to node with automaticallyManagesSubnodes=YES. Node: %@", subnode); [self _addSubnode:subnode]; } @@ -1770,7 +1771,8 @@ static bool disableNotificationsForMovingBetweenParents(ASDisplayNode *from, ASD - (void)replaceSubnode:(ASDisplayNode *)oldSubnode withSubnode:(ASDisplayNode *)replacementSubnode { - ASDisplayNodeAssert(self.automaticallyManagesSubnodes == NO, @"Attempt to manually replace old node with replacement node to node with automaticallyManagesSubnodes=YES. Old Node: %@, replacement node: %@", oldSubnode, replacementSubnode); + // TODO: 2.0 Conversion: Reenable and fix within product code + //ASDisplayNodeAssert(self.automaticallyManagesSubnodes == NO, @"Attempt to manually replace old node with replacement node to node with automaticallyManagesSubnodes=YES. Old Node: %@, replacement node: %@", oldSubnode, replacementSubnode); [self _replaceSubnode:oldSubnode withSubnode:replacementSubnode]; } @@ -1806,7 +1808,8 @@ static NSInteger incrementIfFound(NSInteger i) { - (void)insertSubnode:(ASDisplayNode *)subnode belowSubnode:(ASDisplayNode *)below { - ASDisplayNodeAssert(self.automaticallyManagesSubnodes == NO, @"Attempt to manually insert subnode to node with automaticallyManagesSubnodes=YES. Node: %@", subnode); + // TODO: 2.0 Conversion: Reenable and fix within product code + //ASDisplayNodeAssert(self.automaticallyManagesSubnodes == NO, @"Attempt to manually insert subnode to node with automaticallyManagesSubnodes=YES. Node: %@", subnode); [self _insertSubnode:subnode belowSubnode:below]; } @@ -1857,7 +1860,8 @@ static NSInteger incrementIfFound(NSInteger i) { - (void)insertSubnode:(ASDisplayNode *)subnode aboveSubnode:(ASDisplayNode *)above { - ASDisplayNodeAssert(self.automaticallyManagesSubnodes == NO, @"Attempt to manually insert subnode to node with automaticallyManagesSubnodes=YES. Node: %@", subnode); + // TODO: 2.0 Conversion: Reenable and fix within product code + //ASDisplayNodeAssert(self.automaticallyManagesSubnodes == NO, @"Attempt to manually insert subnode to node with automaticallyManagesSubnodes=YES. Node: %@", subnode); [self _insertSubnode:subnode aboveSubnode:above]; } @@ -1911,7 +1915,8 @@ static NSInteger incrementIfFound(NSInteger i) { - (void)insertSubnode:(ASDisplayNode *)subnode atIndex:(NSInteger)idx { - ASDisplayNodeAssert(self.automaticallyManagesSubnodes == NO, @"Attempt to manually insert subnode to node with automaticallyManagesSubnodes=YES. Node: %@", subnode); + // TODO: 2.0 Conversion: Reenable and fix within product code + //ASDisplayNodeAssert(self.automaticallyManagesSubnodes == NO, @"Attempt to manually insert subnode to node with automaticallyManagesSubnodes=YES. Node: %@", subnode); [self _insertSubnode:subnode atIndex:idx]; } @@ -1989,7 +1994,7 @@ static NSInteger incrementIfFound(NSInteger i) { - (void)removeFromSupernode { - ASDisplayNodeAssert(self.supernode.automaticallyManagesSubnodes == NO, @"Attempt to manually remove subnode from node with automaticallyManagesSubnodes=YES. Node: %@", self); + //ASDisplayNodeAssert(self.supernode.automaticallyManagesSubnodes == NO, @"Attempt to manually remove subnode from node with automaticallyManagesSubnodes=YES. Node: %@", self); [self _removeFromSupernode]; } @@ -3451,6 +3456,15 @@ static const char *ASDisplayNodeDrawingPriorityKey = "ASDrawingPriority"; // Subclass override } +#pragma mark - Deprecated + +ASLayoutElementStyleForwarding + +- (ASLayout *)measureWithSizeRange:(ASSizeRange)constrainedSize +{ + return [self layoutThatFits:constrainedSize parentSize:constrainedSize.max]; +} + ASEnvironmentLayoutExtensibilityForwarding #if TARGET_OS_TV @@ -3486,42 +3500,6 @@ ASEnvironmentLayoutExtensibilityForwarding } #endif -#pragma mark - Deprecated - -- (NSString *)name -{ - return self.debugName; -} - -- (void)setName:(NSString *)name -{ - self.debugName = name; -} - -- (CGSize)measure:(CGSize)constrainedSize -{ - return [self layoutThatFits:ASSizeRangeMake(CGSizeZero, constrainedSize)].size; -} - -- (ASLayout *)measureWithSizeRange:(ASSizeRange)constrainedSize -{ - return [self layoutThatFits:constrainedSize parentSize:constrainedSize.max]; -} - -- (void)setPreferredFrameSize:(CGSize)preferredFrameSize -{ - // Deprecated preferredFrameSize just calls through to set width and height - self.style.preferredSize = preferredFrameSize; - [self invalidateCalculatedLayout]; -} - -- (CGSize)preferredFrameSize -{ - ASLayoutSize size = self.style.preferredLayoutSize; - BOOL isPoints = (size.width.unit == ASDimensionUnitPoints && size.height.unit == ASDimensionUnitPoints); - return isPoints ? CGSizeMake(size.width.value, size.height.value) : CGSizeZero; -} - @end @implementation ASDisplayNode (Debugging) @@ -3637,9 +3615,39 @@ static const char *ASDisplayNodeAssociatedNodeKey = "ASAssociatedNode"; @end +#pragma mark - Deprecated @implementation ASDisplayNode (Deprecated) +- (NSString *)name +{ + return self.debugName; +} + +- (void)setName:(NSString *)name +{ + self.debugName = name; +} + +- (CGSize)measure:(CGSize)constrainedSize +{ + return [self layoutThatFits:ASSizeRangeMake(CGSizeZero, constrainedSize)].size; +} + +- (void)setPreferredFrameSize:(CGSize)preferredFrameSize +{ + // Deprecated preferredFrameSize just calls through to set width and height + self.style.preferredSize = preferredFrameSize; + [self invalidateCalculatedLayout]; +} + +- (CGSize)preferredFrameSize +{ + ASLayoutSize size = self.style.preferredLayoutSize; + BOOL isPoints = (size.width.unit == ASDimensionUnitPoints && size.height.unit == ASDimensionUnitPoints); + return isPoints ? CGSizeMake(size.width.value, size.height.value) : CGSizeZero; +} + - (void)cancelLayoutTransitionsInProgress { [self cancelLayoutTransition]; diff --git a/AsyncDisplayKit/Layout/ASAbsoluteLayoutElement.h b/AsyncDisplayKit/Layout/ASAbsoluteLayoutElement.h index 58c5973ed6..7b6d269259 100644 --- a/AsyncDisplayKit/Layout/ASAbsoluteLayoutElement.h +++ b/AsyncDisplayKit/Layout/ASAbsoluteLayoutElement.h @@ -20,6 +20,11 @@ NS_ASSUME_NONNULL_BEGIN */ @property (nonatomic, assign) CGPoint layoutPosition; + +#pragma mark Deprecated + +@property (nonatomic, assign) ASRelativeSizeRange sizeRange ASDISPLAYNODE_DEPRECATED; + @end NS_ASSUME_NONNULL_END diff --git a/AsyncDisplayKit/Layout/ASAbsoluteLayoutSpec.h b/AsyncDisplayKit/Layout/ASAbsoluteLayoutSpec.h index 5ed9467f47..0f3cc89522 100644 --- a/AsyncDisplayKit/Layout/ASAbsoluteLayoutSpec.h +++ b/AsyncDisplayKit/Layout/ASAbsoluteLayoutSpec.h @@ -43,4 +43,13 @@ NS_ASSUME_NONNULL_BEGIN @end + +#pragma mark - Deprecated + +@interface ASStaticLayoutSpec : ASAbsoluteLayoutSpec + ++ (instancetype)staticLayoutSpecWithChildren:(NSArray> *)children AS_WARN_UNUSED_RESULT ASDISPLAYNODE_DEPRECATED; + +@end + NS_ASSUME_NONNULL_END diff --git a/AsyncDisplayKit/Layout/ASAbsoluteLayoutSpec.mm b/AsyncDisplayKit/Layout/ASAbsoluteLayoutSpec.mm index 5e6377d66f..6b6ff05832 100644 --- a/AsyncDisplayKit/Layout/ASAbsoluteLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASAbsoluteLayoutSpec.mm @@ -10,11 +10,11 @@ #import "ASAbsoluteLayoutSpec.h" -#import "ASLayoutSpecUtilities.h" +#import "ASLayout.h" #import "ASLayoutPrivate.h" +#import "ASLayoutSpecUtilities.h" #import "ASLayoutElementStylePrivate.h" - #pragma mark - ASAbsoluteLayoutSpec @implementation ASAbsoluteLayoutSpec @@ -48,7 +48,7 @@ if (!(self = [super init])) { return nil; } - + _sizing = sizing; self.children = children; @@ -100,6 +100,8 @@ @end +#pragma mark - ASEnvironment + @implementation ASAbsoluteLayoutSpec (ASEnvironment) - (BOOL)supportsUpwardPropagation @@ -109,9 +111,9 @@ @end -@implementation ASAbsoluteLayoutSpec (Debugging) +#pragma mark - Debugging -#pragma mark - ASLayoutElementAsciiArtProtocol +@implementation ASAbsoluteLayoutSpec (Debugging) - (NSString *)debugBoxString { @@ -119,3 +121,20 @@ } @end + + +#pragma mark - ASStaticLayoutSpec + +@implementation ASStaticLayoutSpec : ASAbsoluteLayoutSpec + ++ (instancetype)staticLayoutSpecWithChildren:(NSArray> *)children +{ + return [self absoluteLayoutSpecWithSizing:ASAbsoluteLayoutSpecSizingSizeToFit children:children]; +} + +- (instancetype)initWithChildren:(NSArray *)children +{ + return [super initWithSizing:ASAbsoluteLayoutSpecSizingSizeToFit children:children]; +} + +@end diff --git a/AsyncDisplayKit/Layout/ASDimension.h b/AsyncDisplayKit/Layout/ASDimension.h index 37b8880e2e..5fd9a375f6 100644 --- a/AsyncDisplayKit/Layout/ASDimension.h +++ b/AsyncDisplayKit/Layout/ASDimension.h @@ -333,10 +333,81 @@ ASDISPLAYNODE_INLINE AS_WARN_UNUSED_RESULT ASSizeRange ASLayoutElementSizeResolv #pragma mark - Deprecated +/** + * A dimension relative to constraints to be provided in the future. + * A ASDimension can be one of three types: + * + * "Auto" - This indicated "I have no opinion" and may be resolved in whatever way makes most sense given the circumstances. + * + * "Points" - Just a number. It will always resolve to exactly this amount. + * + * "Percent" - Multiplied to a provided parent amount to resolve a final amount. + */ +typedef NS_ENUM(NSInteger, ASRelativeDimensionType) { + /** This indicates "I have no opinion" and may be resolved in whatever way makes most sense given the circumstances. */ + ASRelativeDimensionTypeAuto, + /** Just a number. It will always resolve to exactly this amount. This is the default type. */ + ASRelativeDimensionTypePoints, + /** Multiplied to a provided parent amount to resolve a final amount. */ + ASRelativeDimensionTypeFraction, +}; + +#define ASRelativeDimension ASDimension +#define ASRelativeSize ASLayoutSize +#define ASRelativeDimensionMakeWithPoints ASDimensionMakeWithPoints +#define ASRelativeDimensionMakeWithFraction ASDimensionMakeWithFraction + /** * Function is deprecated. Use ASSizeRangeMakeWithExactCGSize instead. */ extern AS_WARN_UNUSED_RESULT ASSizeRange ASSizeRangeMakeExactSize(CGSize size) ASDISPLAYNODE_DEPRECATED_MSG("Use ASSizeRangeMakeWithExactCGSize instead."); +/** + Expresses an inclusive range of relative sizes. Used to provide additional constraint to layout. + Used by ASStaticLayoutSpec. + */ +typedef struct { + ASLayoutSize min; + ASLayoutSize max; +} ASRelativeSizeRange; + +extern ASRelativeSizeRange const ASRelativeSizeRangeUnconstrained; + +#pragma mark - ASRelativeDimension + +extern ASDimension ASRelativeDimensionMake(ASRelativeDimensionType type, CGFloat value) ASDISPLAYNODE_DEPRECATED; + +#pragma mark - ASRelativeSize + +extern ASLayoutSize ASRelativeSizeMake(ASRelativeDimension width, ASRelativeDimension height) ASDISPLAYNODE_DEPRECATED; + +/** Convenience constructor to provide size in points. */ +extern ASLayoutSize ASRelativeSizeMakeWithCGSize(CGSize size) ASDISPLAYNODE_DEPRECATED; + +/** Convenience constructor to provide size as a fraction. */ +extern ASLayoutSize ASRelativeSizeMakeWithFraction(CGFloat fraction) ASDISPLAYNODE_DEPRECATED; + +extern BOOL ASRelativeSizeEqualToRelativeSize(ASLayoutSize lhs, ASLayoutSize rhs) ASDISPLAYNODE_DEPRECATED; + +extern NSString *NSStringFromASRelativeSize(ASLayoutSize size) ASDISPLAYNODE_DEPRECATED; + +#pragma mark - ASRelativeSizeRange + +extern ASRelativeSizeRange ASRelativeSizeRangeMake(ASLayoutSize min, ASLayoutSize max) ASDISPLAYNODE_DEPRECATED; + +#pragma mark Convenience constructors to provide an exact size (min == max). +extern ASRelativeSizeRange ASRelativeSizeRangeMakeWithExactRelativeSize(ASLayoutSize exact) ASDISPLAYNODE_DEPRECATED; + +extern ASRelativeSizeRange ASRelativeSizeRangeMakeWithExactCGSize(CGSize exact) ASDISPLAYNODE_DEPRECATED; + +extern ASRelativeSizeRange ASRelativeSizeRangeMakeWithExactFraction(CGFloat fraction) ASDISPLAYNODE_DEPRECATED; + +extern ASRelativeSizeRange ASRelativeSizeRangeMakeWithExactRelativeDimensions(ASRelativeDimension exactWidth, ASRelativeDimension exactHeight) ASDISPLAYNODE_DEPRECATED; + +extern BOOL ASRelativeSizeRangeEqualToRelativeSizeRange(ASRelativeSizeRange lhs, ASRelativeSizeRange rhs) ASDISPLAYNODE_DEPRECATED; + +/** Provided a parent size, compute final dimensions for this RelativeSizeRange to arrive at a SizeRange. */ +extern ASSizeRange ASRelativeSizeRangeResolve(ASRelativeSizeRange relativeSizeRange, CGSize parentSize) ASDISPLAYNODE_DEPRECATED; + NS_ASSUME_NONNULL_END ASDISPLAYNODE_EXTERN_C_END diff --git a/AsyncDisplayKit/Layout/ASDimension.mm b/AsyncDisplayKit/Layout/ASDimension.mm index 260b232e51..ff49a3de0b 100644 --- a/AsyncDisplayKit/Layout/ASDimension.mm +++ b/AsyncDisplayKit/Layout/ASDimension.mm @@ -188,7 +188,86 @@ NSString *NSStringFromASSizeRange(ASSizeRange sizeRange) #pragma mark - Deprecated +ASDimension ASRelativeDimensionMake(ASRelativeDimensionType type, CGFloat value) +{ + if (type == ASRelativeDimensionTypePoints) { + return ASDimensionMakeWithPoints(value); + } else if (type == ASRelativeDimensionTypeFraction) { + return ASDimensionMakeWithFraction(value); + } + + ASDisplayNodeCAssert(NO, @"ASRelativeDimensionMake does not support the given ASRelativeDimensionType"); + return ASDimensionMakeWithPoints(0); +} + ASSizeRange ASSizeRangeMakeExactSize(CGSize size) { return ASSizeRangeMake(size); } + +ASRelativeSizeRange const ASRelativeSizeRangeUnconstrained = {}; + +#pragma mark - ASRelativeSize + +ASLayoutSize ASRelativeSizeMake(ASRelativeDimension width, ASRelativeDimension height) +{ + return ASLayoutSizeMake(width, height); +} + +ASLayoutSize ASRelativeSizeMakeWithCGSize(CGSize size) +{ + return ASRelativeSizeMake(ASRelativeDimensionMakeWithPoints(size.width), + ASRelativeDimensionMakeWithPoints(size.height)); +} + +ASLayoutSize ASRelativeSizeMakeWithFraction(CGFloat fraction) +{ + return ASRelativeSizeMake(ASRelativeDimensionMakeWithFraction(fraction), + ASRelativeDimensionMakeWithFraction(fraction)); +} + +BOOL ASRelativeSizeEqualToRelativeSize(ASLayoutSize lhs, ASLayoutSize rhs) +{ + return ASDimensionEqualToDimension(lhs.width, rhs.width) + && ASDimensionEqualToDimension(lhs.height, rhs.height); +} + + +#pragma mark - ASRelativeSizeRange + +ASRelativeSizeRange ASRelativeSizeRangeMake(ASLayoutSize min, ASLayoutSize max) +{ + ASRelativeSizeRange sizeRange; sizeRange.min = min; sizeRange.max = max; return sizeRange; +} + +ASRelativeSizeRange ASRelativeSizeRangeMakeWithExactRelativeSize(ASLayoutSize exact) +{ + return ASRelativeSizeRangeMake(exact, exact); +} + +ASRelativeSizeRange ASRelativeSizeRangeMakeWithExactCGSize(CGSize exact) +{ + return ASRelativeSizeRangeMakeWithExactRelativeSize(ASRelativeSizeMakeWithCGSize(exact)); +} + +ASRelativeSizeRange ASRelativeSizeRangeMakeWithExactFraction(CGFloat fraction) +{ + return ASRelativeSizeRangeMakeWithExactRelativeSize(ASRelativeSizeMakeWithFraction(fraction)); +} + +ASRelativeSizeRange ASRelativeSizeRangeMakeWithExactRelativeDimensions(ASRelativeDimension exactWidth, ASRelativeDimension exactHeight) +{ + return ASRelativeSizeRangeMakeWithExactRelativeSize(ASRelativeSizeMake(exactWidth, exactHeight)); +} + +BOOL ASRelativeSizeRangeEqualToRelativeSizeRange(ASRelativeSizeRange lhs, ASRelativeSizeRange rhs) +{ + return ASRelativeSizeEqualToRelativeSize(lhs.min, rhs.min) && ASRelativeSizeEqualToRelativeSize(lhs.max, rhs.max); +} + +ASSizeRange ASRelativeSizeRangeResolve(ASRelativeSizeRange relativeSizeRange, + CGSize parentSize) +{ + return ASSizeRangeMake(ASLayoutSizeResolveSize(relativeSizeRange.min, parentSize, parentSize), + ASLayoutSizeResolveSize(relativeSizeRange.max, parentSize, parentSize)); +} diff --git a/AsyncDisplayKit/Layout/ASLayout.h b/AsyncDisplayKit/Layout/ASLayout.h index 0e145c1399..76389398f7 100644 --- a/AsyncDisplayKit/Layout/ASLayout.h +++ b/AsyncDisplayKit/Layout/ASLayout.h @@ -144,6 +144,23 @@ ASDISPLAYNODE_EXTERN_C_END @end +#pragma mark - Deprecated + +@interface ASLayout (Deprecated) + +- (id )layoutableObject ASDISPLAYNODE_DEPRECATED; + ++ (instancetype)layoutWithLayoutableObject:(id)layoutElement + constrainedSizeRange:(ASSizeRange)constrainedSizeRange + size:(CGSize)size ASDISPLAYNODE_DEPRECATED; + ++ (instancetype)layoutWithLayoutableObject:(id)layoutElement + constrainedSizeRange:(ASSizeRange)constrainedSizeRange + size:(CGSize)size + sublayouts:(nullable NSArray *)sublayouts AS_WARN_UNUSED_RESULT ASDISPLAYNODE_DEPRECATED; + +@end + #pragma mark - Debugging @interface ASLayout (Debugging) diff --git a/AsyncDisplayKit/Layout/ASLayout.mm b/AsyncDisplayKit/Layout/ASLayout.mm index 3a7c8d52fa..3b3c4a76b7 100644 --- a/AsyncDisplayKit/Layout/ASLayout.mm +++ b/AsyncDisplayKit/Layout/ASLayout.mm @@ -243,6 +243,30 @@ static inline NSString * descriptionIndents(NSUInteger indents) @end +@implementation ASLayout (Deprecation) + +- (id )layoutableObject +{ + return self.layoutElement; +} + ++ (instancetype)layoutWithLayoutableObject:(id)layoutElement + constrainedSizeRange:(ASSizeRange)constrainedSizeRange + size:(CGSize)size +{ + return [self layoutWithLayoutElement:layoutElement size:size]; +} + ++ (instancetype)layoutWithLayoutableObject:(id)layoutElement + constrainedSizeRange:(ASSizeRange)constrainedSizeRange + size:(CGSize)size + sublayouts:(nullable NSArray *)sublayouts +{ + return [self layoutWithLayoutElement:layoutElement size:size sublayouts:sublayouts]; +} + +@end + ASLayout *ASCalculateLayout(id layoutElement, const ASSizeRange sizeRange, const CGSize parentSize) { ASDisplayNodeCAssertNotNil(layoutElement, @"Not valid layoutElement passed in."); diff --git a/AsyncDisplayKit/Layout/ASLayoutElement.h b/AsyncDisplayKit/Layout/ASLayoutElement.h index fcfd99a10f..1e7b4c3967 100644 --- a/AsyncDisplayKit/Layout/ASLayoutElement.h +++ b/AsyncDisplayKit/Layout/ASLayoutElement.h @@ -50,7 +50,7 @@ NS_ASSUME_NONNULL_BEGIN * access to the options via convenience properties. If you are creating custom layout spec, then you can * extend the backing layout options class to accommodate any new layout options. */ -@protocol ASLayoutElement +@protocol ASLayoutElement #pragma mark - Getter @@ -74,7 +74,6 @@ NS_ASSUME_NONNULL_BEGIN */ @property (nullable, nonatomic, copy) NSString *debugName; - #pragma mark - Calculate layout /** @@ -320,3 +319,4 @@ extern NSString * const ASLayoutElementStyleLayoutPositionProperty; @end NS_ASSUME_NONNULL_END +#define ASLayoutable ASLayoutElement diff --git a/AsyncDisplayKit/Layout/ASLayoutElement.mm b/AsyncDisplayKit/Layout/ASLayoutElement.mm index 2f563124da..affa57314b 100644 --- a/AsyncDisplayKit/Layout/ASLayoutElement.mm +++ b/AsyncDisplayKit/Layout/ASLayoutElement.mm @@ -437,5 +437,23 @@ do {\ return _layoutPosition.load(); } +#pragma mark Deprecated + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +- (ASRelativeSizeRange)sizeRange +{ + return ASRelativeSizeRangeMake(self.minLayoutSize, self.maxLayoutSize); +} + +- (void)setSizeRange:(ASRelativeSizeRange)sizeRange +{ + self.minLayoutSize = sizeRange.min; + self.maxLayoutSize = sizeRange.max; +} + +#pragma clang diagnostic pop + @end diff --git a/AsyncDisplayKit/Layout/ASLayoutElementPrivate.h b/AsyncDisplayKit/Layout/ASLayoutElementPrivate.h index 8dded8c36f..70f3aa917f 100644 --- a/AsyncDisplayKit/Layout/ASLayoutElementPrivate.h +++ b/AsyncDisplayKit/Layout/ASLayoutElementPrivate.h @@ -93,3 +93,122 @@ extern void ASLayoutElementClearCurrentContext(); {\ return _ASEnvironmentLayoutOptionsExtensionGetEdgeInsetsAtIndex(self, idx);\ }\ + + + +#pragma mark - ASLayoutElementStyleForwarding (Deprecated) + +// For the time beeing we are forwading all style related properties on ASDisplayNode and ASLayoutSpec. This define +// help us to not have duplicate code while moving from 1.x to 2.0s +#define ASLayoutElementStyleForwarding \ +\ +@dynamic spacingBefore, spacingAfter, flexGrow, flexShrink, flexBasis, alignSelf, ascender, descender, sizeRange, layoutPosition;\ +\ +_Pragma("mark - ASStackLayoutElement")\ +\ +- (void)setSpacingBefore:(CGFloat)spacingBefore\ +{\ + self.style.spacingBefore = spacingBefore;\ +}\ +\ +- (CGFloat)spacingBefore\ +{\ + return self.style.spacingBefore;\ +}\ +\ +- (void)setSpacingAfter:(CGFloat)spacingAfter\ +{\ + self.style.spacingAfter = spacingAfter;\ +}\ +\ +- (CGFloat)spacingAfter\ +{\ + return self.style.spacingAfter;\ +}\ +\ +- (void)setFlexGrow:(CGFloat)flexGrow\ +{\ + self.style.flexGrow = flexGrow;\ +}\ +\ +- (CGFloat)flexGrow\ +{\ + return self.style.flexGrow;\ +}\ +\ +- (void)setFlexShrink:(CGFloat)flexShrink\ +{\ + self.style.flexShrink = flexShrink;\ +}\ +\ +- (CGFloat)flexShrink\ +{\ + return self.style.flexShrink;\ +}\ +\ +- (void)setFlexBasis:(ASDimension)flexBasis\ +{\ + self.style.flexBasis = flexBasis;\ +}\ +\ +- (ASDimension)flexBasis\ +{\ + return self.style.flexBasis;\ +}\ +\ +- (void)setAlignSelf:(ASStackLayoutAlignSelf)alignSelf\ +{\ + self.style.alignSelf = alignSelf;\ +}\ +\ +- (ASStackLayoutAlignSelf)alignSelf\ +{\ + return self.style.alignSelf;\ +}\ +\ +- (void)setAscender:(CGFloat)ascender\ +{\ + self.style.ascender = ascender;\ +}\ +\ +- (CGFloat)ascender\ +{\ + return self.style.ascender;\ +}\ +\ +- (void)setDescender:(CGFloat)descender\ +{\ + self.style.descender = descender;\ +}\ +\ +- (CGFloat)descender\ +{\ + return self.style.descender;\ +}\ +\ +_Pragma("mark - ASAbsoluteLayoutElement")\ +\ +- (void)setLayoutPosition:(CGPoint)layoutPosition\ +{\ + self.style.layoutPosition = layoutPosition;\ +}\ +\ +- (CGPoint)layoutPosition\ +{\ + return self.style.layoutPosition;\ +}\ +\ +_Pragma("clang diagnostic push")\ +_Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"")\ +\ +- (void)setSizeRange:(ASRelativeSizeRange)sizeRange\ +{\ + self.style.sizeRange = sizeRange;\ +}\ +\ +- (ASRelativeSizeRange)sizeRange\ +{\ + return self.style.sizeRange;\ +}\ +\ +_Pragma("clang diagnostic pop")\ diff --git a/AsyncDisplayKit/Layout/ASLayoutSpec.h b/AsyncDisplayKit/Layout/ASLayoutSpec.h index cce02aaee4..4b583cb9fa 100644 --- a/AsyncDisplayKit/Layout/ASLayoutSpec.h +++ b/AsyncDisplayKit/Layout/ASLayoutSpec.h @@ -16,7 +16,7 @@ NS_ASSUME_NONNULL_BEGIN /** * A layout spec is an immutable object that describes a layout, loosely inspired by React. */ -@interface ASLayoutSpec : NSObject +@interface ASLayoutSpec : NSObject /** * Creation of a layout spec should only happen by a user in layoutSpecThatFits:. During that method, a diff --git a/AsyncDisplayKit/Layout/ASLayoutSpec.mm b/AsyncDisplayKit/Layout/ASLayoutSpec.mm index d1dc4126bc..fec8c53be7 100644 --- a/AsyncDisplayKit/Layout/ASLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASLayoutSpec.mm @@ -83,12 +83,6 @@ #pragma mark - Layout -// Deprecated -- (ASLayout *)measureWithSizeRange:(ASSizeRange)constrainedSize -{ - return [self layoutThatFits:constrainedSize]; -} - - (ASLayout *)layoutThatFits:(ASSizeRange)constrainedSize { return [self layoutThatFits:constrainedSize parentSize:constrainedSize.max]; @@ -293,6 +287,15 @@ ASEnvironmentLayoutExtensibilityForwarding } } +#pragma mark - Deprecated + +- (ASLayout *)measureWithSizeRange:(ASSizeRange)constrainedSize +{ + return [self layoutThatFits:constrainedSize]; +} + +ASLayoutElementStyleForwarding + @end #pragma mark - ASWrapperLayoutSpec diff --git a/AsyncDisplayKitTests/ASDisplayNodeImplicitHierarchyTests.m b/AsyncDisplayKitTests/ASDisplayNodeImplicitHierarchyTests.m index 6944e676e5..51f8c26ee6 100644 --- a/AsyncDisplayKitTests/ASDisplayNodeImplicitHierarchyTests.m +++ b/AsyncDisplayKitTests/ASDisplayNodeImplicitHierarchyTests.m @@ -118,20 +118,21 @@ XCTAssertEqual(node.subnodes[2], node2); } -- (void)testLayoutTransitionWillThrowForManualSubnodeManagement -{ - ASDisplayNode *node1 = [[ASDisplayNode alloc] init]; - node1.debugName = @"node1"; - - ASSpecTestDisplayNode *node = [[ASSpecTestDisplayNode alloc] init]; - node.automaticallyManagesSubnodes = YES; - node.layoutSpecBlock = ^ASLayoutSpec *(ASDisplayNode *weakNode, ASSizeRange constrainedSize){ - return [ASAbsoluteLayoutSpec absoluteLayoutSpecWithChildren:@[node1]]; - }; - - XCTAssertNoThrow([node layoutThatFits:ASSizeRangeMake(CGSizeZero)]); - XCTAssertThrows([node1 removeFromSupernode]); -} +// Disable test for now as we disabled the assertion +//- (void)testLayoutTransitionWillThrowForManualSubnodeManagement +//{ +// ASDisplayNode *node1 = [[ASDisplayNode alloc] init]; +// node1.name = @"node1"; +// +// ASSpecTestDisplayNode *node = [[ASSpecTestDisplayNode alloc] init]; +// node.automaticallyManagesSubnodes = YES; +// node.layoutSpecBlock = ^ASLayoutSpec *(ASDisplayNode *weakNode, ASSizeRange constrainedSize){ +// return [ASAbsoluteLayoutSpec absoluteLayoutSpecWithChildren:@[node1]]; +// }; +// +// XCTAssertNoThrow([node layoutThatFits:ASSizeRangeMake(CGSizeZero)]); +// XCTAssertThrows([node1 removeFromSupernode]); +//} - (void)testLayoutTransitionMeasurementCompletionBlockIsCalledOnMainThread { diff --git a/Base/ASBaseDefines.h b/Base/ASBaseDefines.h index bfa3de4aec..8db12be97e 100755 --- a/Base/ASBaseDefines.h +++ b/Base/ASBaseDefines.h @@ -71,7 +71,7 @@ #endif #ifndef ASDISPLAYNODE_WARN_DEPRECATED -# define ASDISPLAYNODE_WARN_DEPRECATED 1 +# define ASDISPLAYNODE_WARN_DEPRECATED 0 #endif #ifndef ASDISPLAYNODE_DEPRECATED From 30a7edf30f03563c57aabdfc708604b7730edc75 Mon Sep 17 00:00:00 2001 From: Scott Goodson Date: Fri, 21 Oct 2016 13:21:25 -0700 Subject: [PATCH 29/59] [ASLayout] Remove new ASLayoutPrivate.h file and put contents into ASLayoutSpec+Subclasses.h --- AsyncDisplayKit.xcodeproj/project.pbxproj | 4 --- AsyncDisplayKit/ASDisplayNode.mm | 2 +- .../Layout/ASAbsoluteLayoutSpec.mm | 2 +- .../Layout/ASBackgroundLayoutSpec.mm | 2 -- AsyncDisplayKit/Layout/ASInsetLayoutSpec.mm | 4 +-- AsyncDisplayKit/Layout/ASLayout.mm | 3 +-- AsyncDisplayKit/Layout/ASLayoutPrivate.h | 25 ------------------- .../Layout/ASLayoutSpec+Subclasses.h | 11 ++++++++ AsyncDisplayKit/Layout/ASLayoutSpec.mm | 1 - AsyncDisplayKit/Layout/ASOverlayLayoutSpec.mm | 2 +- AsyncDisplayKit/Layout/ASRatioLayoutSpec.mm | 2 +- .../Layout/ASRelativeLayoutSpec.mm | 2 +- .../ASStackBaselinePositionedLayout.mm | 2 +- .../Private/ASStackPositionedLayout.mm | 2 +- 14 files changed, 20 insertions(+), 44 deletions(-) delete mode 100644 AsyncDisplayKit/Layout/ASLayoutPrivate.h diff --git a/AsyncDisplayKit.xcodeproj/project.pbxproj b/AsyncDisplayKit.xcodeproj/project.pbxproj index 390bc3e638..7d308871c3 100644 --- a/AsyncDisplayKit.xcodeproj/project.pbxproj +++ b/AsyncDisplayKit.xcodeproj/project.pbxproj @@ -196,7 +196,6 @@ 68FC85EA1CE29C7D00EDD713 /* ASVisibilityProtocols.h in Headers */ = {isa = PBXBuildFile; fileRef = 68FC85E71CE29C7D00EDD713 /* ASVisibilityProtocols.h */; settings = {ATTRIBUTES = (Public, ); }; }; 68FC85EB1CE29C7D00EDD713 /* ASVisibilityProtocols.m in Sources */ = {isa = PBXBuildFile; fileRef = 68FC85E81CE29C7D00EDD713 /* ASVisibilityProtocols.m */; }; 68FC85EC1CE29C7D00EDD713 /* ASVisibilityProtocols.m in Sources */ = {isa = PBXBuildFile; fileRef = 68FC85E81CE29C7D00EDD713 /* ASVisibilityProtocols.m */; }; - 690457F71DB5131A00B5EE68 /* ASLayoutPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 690457F61DB5131A00B5EE68 /* ASLayoutPrivate.h */; }; 6959433E1D70815300B0EE1F /* ASDisplayNodeLayout.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6959433C1D70815300B0EE1F /* ASDisplayNodeLayout.mm */; }; 6959433F1D70815300B0EE1F /* ASDisplayNodeLayout.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6959433C1D70815300B0EE1F /* ASDisplayNodeLayout.mm */; }; 695943401D70815300B0EE1F /* ASDisplayNodeLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 6959433D1D70815300B0EE1F /* ASDisplayNodeLayout.h */; }; @@ -979,7 +978,6 @@ 68FC85E11CE29B7E00EDD713 /* ASTabBarController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASTabBarController.m; sourceTree = ""; }; 68FC85E71CE29C7D00EDD713 /* ASVisibilityProtocols.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASVisibilityProtocols.h; sourceTree = ""; }; 68FC85E81CE29C7D00EDD713 /* ASVisibilityProtocols.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASVisibilityProtocols.m; sourceTree = ""; }; - 690457F61DB5131A00B5EE68 /* ASLayoutPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASLayoutPrivate.h; path = AsyncDisplayKit/Layout/ASLayoutPrivate.h; sourceTree = ""; }; 6959433C1D70815300B0EE1F /* ASDisplayNodeLayout.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASDisplayNodeLayout.mm; sourceTree = ""; }; 6959433D1D70815300B0EE1F /* ASDisplayNodeLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASDisplayNodeLayout.h; sourceTree = ""; }; 696FCB301D6E46050093471E /* ASBackgroundLayoutSpecSnapshotTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASBackgroundLayoutSpecSnapshotTests.mm; sourceTree = ""; }; @@ -1712,7 +1710,6 @@ 9C49C36E1B853957000B0DD5 /* ASStackLayoutElement.h */, ACF6ED161B17843500DA7C62 /* ASStackLayoutSpec.h */, ACF6ED171B17843500DA7C62 /* ASStackLayoutSpec.mm */, - 690457F61DB5131A00B5EE68 /* ASLayoutPrivate.h */, ); name = Layout; path = ..; @@ -1762,7 +1759,6 @@ 9C70F20D1CDBE9CB007D6C76 /* ASDefaultPlayButton.h in Headers */, 68355B411CB57A6C001D4E68 /* ASImageContainerProtocolCategories.h in Headers */, 7630FFA81C9E267E007A7C0E /* ASVideoNode.h in Headers */, - 690457F71DB5131A00B5EE68 /* ASLayoutPrivate.h in Headers */, B350623F1B010EFD0018CF92 /* _ASAsyncTransactionContainer.h in Headers */, B13CA1011C52004900E031AB /* ASCollectionNode+Beta.h in Headers */, 254C6B7E1BF94DF4003EC431 /* ASTextKitTailTruncater.h in Headers */, diff --git a/AsyncDisplayKit/ASDisplayNode.mm b/AsyncDisplayKit/ASDisplayNode.mm index e6ca7b9269..edb1967acf 100644 --- a/AsyncDisplayKit/ASDisplayNode.mm +++ b/AsyncDisplayKit/ASDisplayNode.mm @@ -30,7 +30,7 @@ #import "ASLayoutElementStylePrivate.h" #import "ASInternalHelpers.h" -#import "ASLayoutPrivate.h" +#import "ASLayoutSpec+Subclasses.h" #import "ASLayoutSpec.h" #import "ASCellNode+Internal.h" #import "ASWeakProxy.h" diff --git a/AsyncDisplayKit/Layout/ASAbsoluteLayoutSpec.mm b/AsyncDisplayKit/Layout/ASAbsoluteLayoutSpec.mm index 6b6ff05832..38be927ef6 100644 --- a/AsyncDisplayKit/Layout/ASAbsoluteLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASAbsoluteLayoutSpec.mm @@ -11,7 +11,7 @@ #import "ASAbsoluteLayoutSpec.h" #import "ASLayout.h" -#import "ASLayoutPrivate.h" +#import "ASLayoutSpec+Subclasses.h" #import "ASLayoutSpecUtilities.h" #import "ASLayoutElementStylePrivate.h" diff --git a/AsyncDisplayKit/Layout/ASBackgroundLayoutSpec.mm b/AsyncDisplayKit/Layout/ASBackgroundLayoutSpec.mm index 3020f4cc86..a94c051a6b 100644 --- a/AsyncDisplayKit/Layout/ASBackgroundLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASBackgroundLayoutSpec.mm @@ -10,9 +10,7 @@ #import "ASBackgroundLayoutSpec.h" #import "ASLayoutSpec+Subclasses.h" - #import "ASAssert.h" -#import "ASLayoutPrivate.h" static NSUInteger const kForegroundChildIndex = 0; static NSUInteger const kBackgroundChildIndex = 1; diff --git a/AsyncDisplayKit/Layout/ASInsetLayoutSpec.mm b/AsyncDisplayKit/Layout/ASInsetLayoutSpec.mm index ca20eadc51..156975a17d 100644 --- a/AsyncDisplayKit/Layout/ASInsetLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASInsetLayoutSpec.mm @@ -9,11 +9,9 @@ // #import "ASInsetLayoutSpec.h" - #import "ASAssert.h" - +#import "ASLayoutSpec+Subclasses.h" #import "ASInternalHelpers.h" -#import "ASLayoutPrivate.h" @interface ASInsetLayoutSpec () { diff --git a/AsyncDisplayKit/Layout/ASLayout.mm b/AsyncDisplayKit/Layout/ASLayout.mm index 3b3c4a76b7..b2f992fe11 100644 --- a/AsyncDisplayKit/Layout/ASLayout.mm +++ b/AsyncDisplayKit/Layout/ASLayout.mm @@ -8,11 +8,10 @@ // of patent rights can be found in the PATENTS file in the same directory. // -#import "ASLayoutPrivate.h" - #import "ASDimension.h" #import "ASInternalHelpers.h" #import "ASLayoutSpecUtilities.h" +#import "ASLayoutSpec+Subclasses.h" #import #import "ASObjectDescriptionHelpers.h" diff --git a/AsyncDisplayKit/Layout/ASLayoutPrivate.h b/AsyncDisplayKit/Layout/ASLayoutPrivate.h deleted file mode 100644 index 1a2ac3d388..0000000000 --- a/AsyncDisplayKit/Layout/ASLayoutPrivate.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// ASLayoutPrivate.h -// AsyncDisplayKit -// -// Created by Michael Schneider on 10/17/16. -// Copyright © 2016 Facebook. All rights reserved. -// - -#pragma once - -#import "ASLayout.h" - -/** - * Private header of ASLayout for internal usage in the framework - */ -@interface ASLayout () - -/** - * Position in parent. Default to CGPointNull. - * - * @discussion When being used as a sublayout, this property must not equal CGPointNull. - */ -@property (nonatomic, assign, readwrite) CGPoint position; - -@end diff --git a/AsyncDisplayKit/Layout/ASLayoutSpec+Subclasses.h b/AsyncDisplayKit/Layout/ASLayoutSpec+Subclasses.h index 60c66a9106..84d5a9db35 100644 --- a/AsyncDisplayKit/Layout/ASLayoutSpec+Subclasses.h +++ b/AsyncDisplayKit/Layout/ASLayoutSpec+Subclasses.h @@ -61,4 +61,15 @@ NS_ASSUME_NONNULL_BEGIN @end +@interface ASLayout () + +/** + * Position in parent. Default to CGPointNull. + * + * @discussion When being used as a sublayout, this property must not equal CGPointNull. + */ +@property (nonatomic, assign, readwrite) CGPoint position; + +@end + NS_ASSUME_NONNULL_END diff --git a/AsyncDisplayKit/Layout/ASLayoutSpec.mm b/AsyncDisplayKit/Layout/ASLayoutSpec.mm index fec8c53be7..3aa316aab2 100644 --- a/AsyncDisplayKit/Layout/ASLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASLayoutSpec.mm @@ -11,7 +11,6 @@ #import "ASLayoutSpec.h" #import "ASLayoutSpecPrivate.h" #import "ASLayoutSpec+Subclasses.h" -#import "ASLayoutPrivate.h" #import "ASLayoutElementStylePrivate.h" @implementation ASLayoutSpec diff --git a/AsyncDisplayKit/Layout/ASOverlayLayoutSpec.mm b/AsyncDisplayKit/Layout/ASOverlayLayoutSpec.mm index fb0b939fbf..b38fe83a86 100644 --- a/AsyncDisplayKit/Layout/ASOverlayLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASOverlayLayoutSpec.mm @@ -12,7 +12,7 @@ #import "ASLayoutSpec+Subclasses.h" #import "ASAssert.h" -#import "ASLayoutPrivate.h" +#import "ASLayoutSpec+Subclasses.h" static NSUInteger const kUnderlayChildIndex = 0; static NSUInteger const kOverlayChildIndex = 1; diff --git a/AsyncDisplayKit/Layout/ASRatioLayoutSpec.mm b/AsyncDisplayKit/Layout/ASRatioLayoutSpec.mm index 00c1d584f3..1155af720e 100644 --- a/AsyncDisplayKit/Layout/ASRatioLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASRatioLayoutSpec.mm @@ -17,7 +17,7 @@ #import "ASAssert.h" #import "ASInternalHelpers.h" -#import "ASLayoutPrivate.h" +#import "ASLayoutSpec+Subclasses.h" #pragma mark - ASRatioLayoutSpec diff --git a/AsyncDisplayKit/Layout/ASRelativeLayoutSpec.mm b/AsyncDisplayKit/Layout/ASRelativeLayoutSpec.mm index d8f9bd717a..1072fb443d 100644 --- a/AsyncDisplayKit/Layout/ASRelativeLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASRelativeLayoutSpec.mm @@ -13,7 +13,7 @@ #import "ASRelativeLayoutSpec.h" #import "ASInternalHelpers.h" -#import "ASLayoutPrivate.h" +#import "ASLayoutSpec+Subclasses.h" @implementation ASRelativeLayoutSpec diff --git a/AsyncDisplayKit/Private/ASStackBaselinePositionedLayout.mm b/AsyncDisplayKit/Private/ASStackBaselinePositionedLayout.mm index 5c0a86cbe9..081d7cf42c 100644 --- a/AsyncDisplayKit/Private/ASStackBaselinePositionedLayout.mm +++ b/AsyncDisplayKit/Private/ASStackBaselinePositionedLayout.mm @@ -11,7 +11,7 @@ #import "ASStackBaselinePositionedLayout.h" #import "ASLayoutSpecUtilities.h" -#import "ASLayoutPrivate.h" +#import "ASLayoutSpec+Subclasses.h" static CGFloat baselineForItem(const ASStackLayoutSpecStyle &style, const ASLayout *layout) { diff --git a/AsyncDisplayKit/Private/ASStackPositionedLayout.mm b/AsyncDisplayKit/Private/ASStackPositionedLayout.mm index 16fdd9ea1a..f00478b67a 100644 --- a/AsyncDisplayKit/Private/ASStackPositionedLayout.mm +++ b/AsyncDisplayKit/Private/ASStackPositionedLayout.mm @@ -14,7 +14,7 @@ #import "ASInternalHelpers.h" #import "ASLayoutSpecUtilities.h" -#import "ASLayoutPrivate.h" +#import "ASLayoutSpec+Subclasses.h" static CGFloat crossOffset(const ASStackLayoutSpecStyle &style, const ASStackUnpositionedItem &l, From c65c233613992bd1fc9f27d134d63122bdfd32a1 Mon Sep 17 00:00:00 2001 From: Garrett Moon Date: Fri, 21 Oct 2016 17:26:16 -0700 Subject: [PATCH 30/59] Fix to beta 5 of PINRemoteImage (#2464) Beta 4 added a PINCache subspec which was required for ASDK. However, Beta 5 reverted this in an attempt to fix automatically updated versions of ASDK. So this patch sets the specific version to beta 5 until we're ready to launch. --- AsyncDisplayKit.podspec | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/AsyncDisplayKit.podspec b/AsyncDisplayKit.podspec index 9e146ed38d..f5dba4322d 100644 --- a/AsyncDisplayKit.podspec +++ b/AsyncDisplayKit.podspec @@ -59,8 +59,7 @@ Pod::Spec.new do |spec| spec.subspec 'PINRemoteImage' do |pin| pin.xcconfig = { 'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) PIN_REMOTE_IMAGE=1' } - pin.dependency 'PINRemoteImage/iOS', '>= 3.0.0-beta.4' - pin.dependency 'PINRemoteImage/PINCache' + pin.dependency 'PINRemoteImage/iOS', '= 3.0.0-beta.5' pin.dependency 'AsyncDisplayKit/Core' end From 4dca05767bf7f5d555746d8cb9e444de51bd458b Mon Sep 17 00:00:00 2001 From: romankl Date: Sat, 22 Oct 2016 02:41:07 +0200 Subject: [PATCH 31/59] switch snapshot-test-case back to the main repo (#2454) The latest version (v2.1.4) brought back the deployment target `s.ios.deployment_target = '7.0'`. --- Podfile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Podfile b/Podfile index 9edf80f1e6..a625c28556 100644 --- a/Podfile +++ b/Podfile @@ -4,6 +4,5 @@ platform :ios, '7.0' target :'AsyncDisplayKitTests' do pod 'OCMock', '~> 2.2' - # this is identical to FBSnapshotTestCase 2.1.3 except that the deployment was changed from 8.0 -> 7.0 - pod 'FBSnapshotTestCase/Core', :git => "https://github.com/hannahmbanana/ios-snapshot-test-case.git" + pod 'FBSnapshotTestCase/Core', '~> 2.1' end From 3638feffd48fd8a7b6d437d1ed8bfb23cd81687b Mon Sep 17 00:00:00 2001 From: george-gw Date: Mon, 24 Oct 2016 18:30:09 +0200 Subject: [PATCH 32/59] Added selection API to ASTableNode and ASCollectionNode (#2453) * Added selection API to ASTableNode and ASCollectionNode (#2450) * Updated test case to use collectionNode instead of collectionView for the selection tests. * Fixed typos. Added asserts for main thread. Updated ASCollectionViewTests for multiple selections for nodes. * Added assigns to the different properties. --- AsyncDisplayKit/ASCollectionNode.h | 44 +++++++ AsyncDisplayKit/ASCollectionNode.mm | 70 +++++++++++- AsyncDisplayKit/ASTableNode.h | 53 +++++++++ AsyncDisplayKit/ASTableNode.mm | 108 +++++++++++++++++- AsyncDisplayKitTests/ASCollectionViewTests.mm | 49 ++++++-- 5 files changed, 311 insertions(+), 13 deletions(-) diff --git a/AsyncDisplayKit/ASCollectionNode.h b/AsyncDisplayKit/ASCollectionNode.h index b36d94ee88..6e3c5fd9ad 100644 --- a/AsyncDisplayKit/ASCollectionNode.h +++ b/AsyncDisplayKit/ASCollectionNode.h @@ -74,6 +74,20 @@ NS_ASSUME_NONNULL_BEGIN */ @property (weak, nonatomic) id dataSource; +/** + * A Boolean value that indicates whether users can select items in the collection node. + * If the value of this property is YES (the default), users can select items. If you want more fine-grained control over the selection of items, you must provide a delegate object and implement the appropriate methods of the UICollectionNodeDelegate protocol. + */ +@property (nonatomic, assign) BOOL allowsSelection; + +/** + * A Boolean value that determines whether users can select more than one item in the collection node. + * This property controls whether multiple items can be selected simultaneously. The default value of this property is NO. + * When the value of this property is YES, tapping a cell adds it to the current selection (assuming the delegate permits the cell to be selected). Tapping the cell again removes it from the selection. + */ +@property (nonatomic, assign) BOOL allowsMultipleSelection; + + /** * Tuning parameters for a range type in full mode. * @@ -272,6 +286,36 @@ NS_ASSUME_NONNULL_BEGIN */ - (void)relayoutItems; +#pragma mark - Selection + +/** + * Selects the item at the specified index path and optionally scrolls it into view. + * If the `allowsSelection` property is NO, calling this method has no effect. If there is an existing selection with a different index path and the `allowsMultipleSelection` property is NO, calling this method replaces the previous selection. + * This method does not cause any selection-related delegate methods to be called. + * + * @param indexPath The index path of the item to select. Specifying nil for this parameter clears the current selection. + * + * @param animated Specify YES to animate the change in the selection or NO to make the change without animating it. + * + * @param scrollPosition An option that specifies where the item should be positioned when scrolling finishes. For a list of possible values, see `UICollectionViewScrollPosition`. + * + * @discussion This method must be called from the main thread. + */ +- (void)selectItemAtIndexPath:(nullable NSIndexPath *)indexPath animated:(BOOL)animated scrollPosition:(UICollectionViewScrollPosition)scrollPosition; + +/** + * Deselects the item at the specified index. + * If the allowsSelection property is NO, calling this method has no effect. + * This method does not cause any selection-related delegate methods to be called. + * + * @param indexPath The index path of the item to select. Specifying nil for this parameter clears the current selection. + * + * @param animated Specify YES to animate the change in the selection or NO to make the change without animating it. + * + * @discussion This method must be called from the main thread. + */ +- (void)deselectItemAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated; + #pragma mark - Querying Data /** diff --git a/AsyncDisplayKit/ASCollectionNode.mm b/AsyncDisplayKit/ASCollectionNode.mm index ab6123be31..b9dcc1c676 100644 --- a/AsyncDisplayKit/ASCollectionNode.mm +++ b/AsyncDisplayKit/ASCollectionNode.mm @@ -27,7 +27,9 @@ @interface _ASCollectionPendingState : NSObject @property (weak, nonatomic) id delegate; @property (weak, nonatomic) id dataSource; -@property (assign, nonatomic) ASLayoutRangeMode rangeMode; +@property (nonatomic, assign) ASLayoutRangeMode rangeMode; +@property (nonatomic, assign) BOOL allowsSelection; // default is YES +@property (nonatomic, assign) BOOL allowsMultipleSelection; // default is NO @end @implementation _ASCollectionPendingState @@ -37,6 +39,8 @@ self = [super init]; if (self) { _rangeMode = ASLayoutRangeModeCount; + _allowsSelection = YES; + _allowsMultipleSelection = NO; } return self; } @@ -143,9 +147,11 @@ if (_pendingState) { _ASCollectionPendingState *pendingState = _pendingState; - self.pendingState = nil; - view.asyncDelegate = pendingState.delegate; - view.asyncDataSource = pendingState.dataSource; + self.pendingState = nil; + view.asyncDelegate = pendingState.delegate; + view.asyncDataSource = pendingState.dataSource; + view.allowsSelection = pendingState.allowsSelection; + view.allowsMultipleSelection = pendingState.allowsMultipleSelection; if (pendingState.rangeMode != ASLayoutRangeModeCount) { [view.rangeController updateCurrentRangeWithMode:pendingState.rangeMode]; @@ -251,6 +257,44 @@ } } +- (void)setAllowsSelection:(BOOL)allowsSelection +{ + if ([self pendingState]) { + _pendingState.allowsSelection = allowsSelection; + } else { + ASDisplayNodeAssert([self isNodeLoaded], @"ASCollectionNode should be loaded if pendingState doesn't exist"); + self.view.allowsSelection = allowsSelection; + } +} + +- (BOOL)allowsSelection +{ + if ([self pendingState]) { + return _pendingState.allowsSelection; + } else { + return self.view.allowsSelection; + } +} + +- (void)setAllowsMultipleSelection:(BOOL)allowsMultipleSelection +{ + if ([self pendingState]) { + _pendingState.allowsMultipleSelection = allowsMultipleSelection; + } else { + ASDisplayNodeAssert([self isNodeLoaded], @"ASCollectionNode should be loaded if pendingState doesn't exist"); + self.view.allowsMultipleSelection = allowsMultipleSelection; + } +} + +- (BOOL)allowsMultipleSelection +{ + if ([self pendingState]) { + return _pendingState.allowsMultipleSelection; + } else { + return self.view.allowsMultipleSelection; + } +} + #pragma mark - Range Tuning - (ASRangeTuningParameters)tuningParametersForRangeType:(ASLayoutRangeType)rangeType @@ -273,6 +317,24 @@ return [self.rangeController setTuningParameters:tuningParameters forRangeMode:rangeMode rangeType:rangeType]; } +#pragma mark - Selection + +- (void)selectItemAtIndexPath:(nullable NSIndexPath *)indexPath animated:(BOOL)animated scrollPosition:(UICollectionViewScrollPosition)scrollPosition +{ + ASDisplayNodeAssertMainThread(); + // TODO: Solve this in a way to be able to remove this restriction (https://github.com/facebook/AsyncDisplayKit/pull/2453#discussion_r84515457) + ASDisplayNodeAssert([self isNodeLoaded], @"ASCollectionNode should be loaded before calling selectItemAtIndexPath"); + [self.view selectItemAtIndexPath:indexPath animated:animated scrollPosition:scrollPosition]; +} + +- (void)deselectItemAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated +{ + ASDisplayNodeAssertMainThread(); + // TODO: Solve this in a way to be able to remove this restriction (https://github.com/facebook/AsyncDisplayKit/pull/2453#discussion_r84515457) + ASDisplayNodeAssert([self isNodeLoaded], @"ASCollectionNode should be loaded before calling deselectItemAtIndexPath"); + [self.view deselectItemAtIndexPath:indexPath animated:animated]; +} + #pragma mark - Querying Data - (NSInteger)numberOfItemsInSection:(NSInteger)section diff --git a/AsyncDisplayKit/ASTableNode.h b/AsyncDisplayKit/ASTableNode.h index 854c1136f6..3111704b54 100644 --- a/AsyncDisplayKit/ASTableNode.h +++ b/AsyncDisplayKit/ASTableNode.h @@ -35,6 +35,27 @@ NS_ASSUME_NONNULL_BEGIN @property (weak, nonatomic) id delegate; @property (weak, nonatomic) id dataSource; +/* + * A Boolean value that determines whether users can select a row. + * If the value of this property is YES (the default), users can select rows. If you set it to NO, they cannot select rows. Setting this property affects cell selection only when the table view is not in editing mode. If you want to restrict selection of cells in editing mode, use `allowsSelectionDuringEditing`. + */ +@property (nonatomic, assign) BOOL allowsSelection; +/* + * A Boolean value that determines whether users can select cells while the table view is in editing mode. + * If the value of this property is YES, users can select rows during editing. The default value is NO. If you want to restrict selection of cells regardless of mode, use allowsSelection. + */ +@property (nonatomic, assign) BOOL allowsSelectionDuringEditing; +/* + * A Boolean value that determines whether users can select more than one row outside of editing mode. + * This property controls whether multiple rows can be selected simultaneously outside of editing mode. When the value of this property is YES, each row that is tapped acquires a selected appearance. Tapping the row again removes the selected appearance. If you access indexPathsForSelectedRows, you can get the index paths that identify the selected rows. + */ +@property (nonatomic, assign) BOOL allowsMultipleSelection; +/* + * A Boolean value that controls whether users can select more than one cell simultaneously in editing mode. + * The default value of this property is NO. If you set it to YES, check marks appear next to selected rows in editing mode. In addition, UITableView does not query for editing styles when it goes into editing mode. If you access indexPathsForSelectedRows, you can get the index paths that identify the selected rows. + */ +@property (nonatomic, assign) BOOL allowsMultipleSelectionDuringEditing; + /** * Tuning parameters for a range type in full mode. * @@ -230,6 +251,38 @@ NS_ASSUME_NONNULL_BEGIN */ - (void)moveRowAtIndexPath:(NSIndexPath *)indexPath toIndexPath:(NSIndexPath *)newIndexPath; +#pragma mark - Selection + +/** + * Selects a row in the table view identified by index path, optionally scrolling the row to a location in the table view. + * This method does not cause any selection-related delegate methods to be called. + * + * @param indexPath An index path identifying a row in the table view. + * + * @param animated Specify YES to animate the change in the selection or NO to make the change without animating it. + * + * @param scrollPosition A constant that identifies a relative position in the table view (top, middle, bottom) for the row when scrolling concludes. See `UITableViewScrollPosition` for descriptions of valid constants. + * + * @discussion This method must be called from the main thread. + */ +- (void)selectRowAtIndexPath:(nullable NSIndexPath *)indexPath animated:(BOOL)animated scrollPosition:(UITableViewScrollPosition)scrollPosition; + +/* + * Deselects a given row identified by index path, with an option to animate the deselection. + * This method does not cause any selection-related delegate methods to be called. + * Calling this method does not cause any scrolling to the deselected row. + * + * @param indexPath An index path identifying a row in the table view. + * + * @param animated Specify YES to animate the change in the selection or NO to make the change without animating it. + * + * @discussion This method must be called from the main thread. + */ +- (void)deselectRowAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated; + + +#pragma mark - Querying Data + /** * Retrieves the number of rows in the given section. * diff --git a/AsyncDisplayKit/ASTableNode.mm b/AsyncDisplayKit/ASTableNode.mm index dc5daa0dae..5fa32a1425 100644 --- a/AsyncDisplayKit/ASTableNode.mm +++ b/AsyncDisplayKit/ASTableNode.mm @@ -24,7 +24,11 @@ @interface _ASTablePendingState : NSObject @property (weak, nonatomic) id delegate; @property (weak, nonatomic) id dataSource; -@property (assign, nonatomic) ASLayoutRangeMode rangeMode; +@property (nonatomic, assign) ASLayoutRangeMode rangeMode; +@property (nonatomic, assign) BOOL allowsSelection; +@property (nonatomic, assign) BOOL allowsSelectionDuringEditing; +@property (nonatomic, assign) BOOL allowsMultipleSelection; +@property (nonatomic, assign) BOOL allowsMultipleSelectionDuringEditing; @end @implementation _ASTablePendingState @@ -33,6 +37,10 @@ self = [super init]; if (self) { _rangeMode = ASLayoutRangeModeCount; + _allowsSelection = YES; + _allowsSelectionDuringEditing = NO; + _allowsMultipleSelection = NO; + _allowsMultipleSelectionDuringEditing = NO; } return self; } @@ -104,6 +112,10 @@ self.pendingState = nil; view.asyncDelegate = pendingState.delegate; view.asyncDataSource = pendingState.dataSource; + view.allowsSelection = pendingState.allowsSelection; + view.allowsSelectionDuringEditing = pendingState.allowsSelectionDuringEditing; + view.allowsMultipleSelection = pendingState.allowsMultipleSelection; + view.allowsMultipleSelectionDuringEditing = pendingState.allowsMultipleSelectionDuringEditing; if (pendingState.rangeMode != ASLayoutRangeModeCount) { [view.rangeController updateCurrentRangeWithMode:pendingState.rangeMode]; } @@ -215,6 +227,82 @@ } } +- (void)setAllowsSelection:(BOOL)allowsSelection +{ + if ([self pendingState]) { + _pendingState.allowsSelection = allowsSelection; + } else { + ASDisplayNodeAssert([self isNodeLoaded], @"ASTableNode should be loaded if pendingState doesn't exist"); + self.view.allowsSelection = allowsSelection; + } +} + +- (BOOL)allowsSelection +{ + if ([self pendingState]) { + return _pendingState.allowsSelection; + } else { + return self.view.allowsSelection; + } +} + +- (void)setAllowsSelectionDuringEditing:(BOOL)allowsSelectionDuringEditing +{ + if ([self pendingState]) { + _pendingState.allowsSelectionDuringEditing = allowsSelectionDuringEditing; + } else { + ASDisplayNodeAssert([self isNodeLoaded], @"ASTableNode should be loaded if pendingState doesn't exist"); + self.view.allowsSelectionDuringEditing = allowsSelectionDuringEditing; + } +} + +- (BOOL)allowsSelectionDuringEditing +{ + if ([self pendingState]) { + return _pendingState.allowsSelectionDuringEditing; + } else { + return self.view.allowsSelectionDuringEditing; + } +} + +- (void)setAllowsMultipleSelection:(BOOL)allowsMultipleSelection +{ + if ([self pendingState]) { + _pendingState.allowsMultipleSelection = allowsMultipleSelection; + } else { + ASDisplayNodeAssert([self isNodeLoaded], @"ASTableNode should be loaded if pendingState doesn't exist"); + self.view.allowsMultipleSelection = allowsMultipleSelection; + } +} + +- (BOOL)allowsMultipleSelection +{ + if ([self pendingState]) { + return _pendingState.allowsMultipleSelection; + } else { + return self.view.allowsMultipleSelection; + } +} + +- (void)setAllowsMultipleSelectionDuringEditing:(BOOL)allowsMultipleSelectionDuringEditing +{ + if ([self pendingState]) { + _pendingState.allowsMultipleSelectionDuringEditing = allowsMultipleSelectionDuringEditing; + } else { + ASDisplayNodeAssert([self isNodeLoaded], @"ASTableNode should be loaded if pendingState doesn't exist"); + self.view.allowsMultipleSelectionDuringEditing = allowsMultipleSelectionDuringEditing; + } +} + +- (BOOL)allowsMultipleSelectionDuringEditing +{ + if ([self pendingState]) { + return _pendingState.allowsMultipleSelectionDuringEditing; + } else { + return self.view.allowsMultipleSelectionDuringEditing; + } +} + #pragma mark ASRangeControllerUpdateRangeProtocol - (void)updateCurrentRangeWithMode:(ASLayoutRangeMode)rangeMode @@ -253,6 +341,24 @@ ASEnvironmentCollectionTableSetEnvironmentState(_environmentStateLock) return [self.rangeController setTuningParameters:tuningParameters forRangeMode:rangeMode rangeType:rangeType]; } +#pragma mark - Selection + +- (void)selectRowAtIndexPath:(nullable NSIndexPath *)indexPath animated:(BOOL)animated scrollPosition:(UITableViewScrollPosition)scrollPosition +{ + ASDisplayNodeAssertMainThread(); + // TODO: Solve this in a way to be able to remove this restriction (https://github.com/facebook/AsyncDisplayKit/pull/2453#discussion_r84515457) + ASDisplayNodeAssert([self isNodeLoaded], @"ASTableNode should be loaded before calling selectRowAtIndexPath"); + [self.view selectRowAtIndexPath:indexPath animated:animated scrollPosition:scrollPosition]; +} + +- (void)deselectRowAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated +{ + ASDisplayNodeAssertMainThread(); + // TODO: Solve this in a way to be able to remove this restriction (https://github.com/facebook/AsyncDisplayKit/pull/2453#discussion_r84515457) + ASDisplayNodeAssert([self isNodeLoaded], @"ASTableNode should be loaded before calling deselectRowAtIndexPath"); + [self.view deselectRowAtIndexPath:indexPath animated:animated]; +} + #pragma mark - Querying Data - (NSInteger)numberOfRowsInSection:(NSInteger)section diff --git a/AsyncDisplayKitTests/ASCollectionViewTests.mm b/AsyncDisplayKitTests/ASCollectionViewTests.mm index d8940b2b53..0bd538cacb 100644 --- a/AsyncDisplayKitTests/ASCollectionViewTests.mm +++ b/AsyncDisplayKitTests/ASCollectionViewTests.mm @@ -222,27 +222,60 @@ NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:0]; ASCellNode *node = [testController.collectionView nodeForItemAtIndexPath:indexPath]; - + + NSInteger setSelectedCount = 0; // selecting node should select cell node.selected = YES; + ++setSelectedCount; XCTAssertTrue([[testController.collectionView indexPathsForSelectedItems] containsObject:indexPath], @"Selecting node should update cell selection."); // deselecting node should deselect cell node.selected = NO; + ++setSelectedCount; XCTAssertTrue([[testController.collectionView indexPathsForSelectedItems] isEqualToArray:@[]], @"Deselecting node should update cell selection."); - // selecting cell via collectionView should select node - [testController.collectionView selectItemAtIndexPath:indexPath animated:NO scrollPosition:UICollectionViewScrollPositionNone]; + // selecting cell via collectionNode should select node + ++setSelectedCount; + [testController.collectionNode selectItemAtIndexPath:indexPath animated:NO scrollPosition:UICollectionViewScrollPositionNone]; XCTAssertTrue(node.isSelected == YES, @"Selecting cell should update node selection."); - // deselecting cell via collectionView should deselect node - [testController.collectionView deselectItemAtIndexPath:indexPath animated:NO]; + // deselecting cell via collectionNode should deselect node + ++setSelectedCount; + [testController.collectionNode deselectItemAtIndexPath:indexPath animated:NO]; XCTAssertTrue(node.isSelected == NO, @"Deselecting cell should update node selection."); // select the cell again, scroll down and back up, and check that the state persisted - [testController.collectionView selectItemAtIndexPath:indexPath animated:NO scrollPosition:UICollectionViewScrollPositionNone]; + [testController.collectionNode selectItemAtIndexPath:indexPath animated:NO scrollPosition:UICollectionViewScrollPositionNone]; + ++setSelectedCount; XCTAssertTrue(node.isSelected == YES, @"Selecting cell should update node selection."); - + + testController.collectionNode.allowsMultipleSelection = YES; + + NSIndexPath *indexPath2 = [NSIndexPath indexPathForItem:1 inSection:0]; + ASCellNode *node2 = [testController.collectionView nodeForItemAtIndexPath:indexPath2]; + + // selecting cell via collectionNode should select node + [testController.collectionNode selectItemAtIndexPath:indexPath2 animated:NO scrollPosition:UICollectionViewScrollPositionNone]; + XCTAssertTrue(node2.isSelected == YES, @"Selecting cell should update node selection."); + + XCTAssertTrue([[testController.collectionView indexPathsForSelectedItems] containsObject:indexPath] && + [[testController.collectionView indexPathsForSelectedItems] containsObject:indexPath2], + @"Selecting multiple cells should result in those cells being in the array of selectedItems."); + + // deselecting node should deselect cell + node.selected = NO; + ++setSelectedCount; + XCTAssertTrue(![[testController.collectionView indexPathsForSelectedItems] containsObject:indexPath] && + [[testController.collectionView indexPathsForSelectedItems] containsObject:indexPath2], @"Deselecting node should update array of selectedItems."); + + node.selected = YES; + ++setSelectedCount; + XCTAssertTrue([[testController.collectionView indexPathsForSelectedItems] containsObject:indexPath], @"Selecting node should update cell selection."); + + node2.selected = NO; + XCTAssertTrue([[testController.collectionView indexPathsForSelectedItems] containsObject:indexPath] && + ![[testController.collectionView indexPathsForSelectedItems] containsObject:indexPath2], @"Deselecting node should update array of selectedItems."); + // reload cell (-prepareForReuse is called) & check that selected state is preserved [testController.collectionView setContentOffset:CGPointMake(0,testController.collectionView.bounds.size.height)]; [testController.collectionView layoutIfNeeded]; @@ -256,7 +289,7 @@ XCTAssertTrue(node.isSelected == NO, @"Deselecting cell should update node selection."); // check setSelected not called extra times - XCTAssertTrue([(ASTextCellNodeWithSetSelectedCounter *)node setSelectedCounter] == 6, @"setSelected: should not be called on node multiple times."); + XCTAssertTrue([(ASTextCellNodeWithSetSelectedCounter *)node setSelectedCounter] == (setSelectedCount + 1), @"setSelected: should not be called on node multiple times."); } - (void)testTuningParametersWithExplicitRangeMode From 97e23776e44a68454943e3e2fe9f4d5a3bd6a76d Mon Sep 17 00:00:00 2001 From: Hannah Troisi Date: Mon, 24 Oct 2016 09:42:04 -0700 Subject: [PATCH 33/59] [ASTableNode] expose ASTableView's -visibleNodes (#2449) * expose ASTableView's -visibleNodes getter at the ASTableNode level * add safegaurds * make visibleNodes a read only property for ASTableNode * make collectionNode .visibleNodes property --- AsyncDisplayKit/ASCollectionNode.h | 4 ++-- AsyncDisplayKit/ASCollectionNode.mm | 3 ++- AsyncDisplayKit/ASTableNode.h | 7 +++++++ AsyncDisplayKit/ASTableNode.mm | 6 ++++++ 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/AsyncDisplayKit/ASCollectionNode.h b/AsyncDisplayKit/ASCollectionNode.h index 6e3c5fd9ad..d5d799d68a 100644 --- a/AsyncDisplayKit/ASCollectionNode.h +++ b/AsyncDisplayKit/ASCollectionNode.h @@ -335,9 +335,9 @@ NS_ASSUME_NONNULL_BEGIN /** * Similar to -visibleCells. * - * @return an array containing the nodes being displayed on screen. + * @return an array containing the nodes being displayed on screen. This must be called on the main thread. */ -- (NSArray<__kindof ASCellNode *> *)visibleNodes AS_WARN_UNUSED_RESULT; +@property(readonly, copy) NSArray<__kindof ASCellNode *> *visibleNodes; /** * Retrieves the node for the item at the given index path. diff --git a/AsyncDisplayKit/ASCollectionNode.mm b/AsyncDisplayKit/ASCollectionNode.mm index b9dcc1c676..69f8bc25d6 100644 --- a/AsyncDisplayKit/ASCollectionNode.mm +++ b/AsyncDisplayKit/ASCollectionNode.mm @@ -349,7 +349,8 @@ - (NSArray<__kindof ASCellNode *> *)visibleNodes { - return [self.view visibleNodes]; + ASDisplayNodeAssertMainThread(); + return self.isNodeLoaded ? [self.view visibleNodes] : @[]; } - (NSIndexPath *)indexPathForNode:(ASCellNode *)cellNode diff --git a/AsyncDisplayKit/ASTableNode.h b/AsyncDisplayKit/ASTableNode.h index 3111704b54..540f644aaf 100644 --- a/AsyncDisplayKit/ASTableNode.h +++ b/AsyncDisplayKit/ASTableNode.h @@ -339,6 +339,13 @@ NS_ASSUME_NONNULL_BEGIN */ - (NSInteger)tableNode:(ASTableNode *)tableNode numberOfRowsInSection:(NSInteger)section; +/** + * Similar to -visibleCells. + * + * @return an array containing the nodes being displayed on screen. This must be called on the main thread. + */ +@property(readonly, copy) NSArray<__kindof ASCellNode *> *visibleNodes; + /** * Asks the data source for a block to create a node to represent the row at the given index path. * The block will be run by the table node concurrently in the background before the row is inserted diff --git a/AsyncDisplayKit/ASTableNode.mm b/AsyncDisplayKit/ASTableNode.mm index 5fa32a1425..f2f2f7e126 100644 --- a/AsyncDisplayKit/ASTableNode.mm +++ b/AsyncDisplayKit/ASTableNode.mm @@ -371,6 +371,12 @@ ASEnvironmentCollectionTableSetEnvironmentState(_environmentStateLock) return [self.dataController numberOfSections]; } +- (NSArray<__kindof ASCellNode *> *)visibleNodes +{ + ASDisplayNodeAssertMainThread(); + return self.isNodeLoaded ? [self.view visibleNodes] : @[]; +} + - (NSIndexPath *)indexPathForNode:(ASCellNode *)cellNode { return [self.dataController indexPathForNode:cellNode]; From 4e580b96dca22e56c443ea606f178d2fd22d2e7a Mon Sep 17 00:00:00 2001 From: Michael Schneider Date: Mon, 24 Oct 2016 09:59:44 -0700 Subject: [PATCH 34/59] Add support for multiple children to ASWrapperLayoutSpec (#2469) --- AsyncDisplayKit/Layout/ASLayoutSpec.h | 20 +++++++++++++---- AsyncDisplayKit/Layout/ASLayoutSpec.mm | 31 +++++++++++++++++++++++--- 2 files changed, 44 insertions(+), 7 deletions(-) diff --git a/AsyncDisplayKit/Layout/ASLayoutSpec.h b/AsyncDisplayKit/Layout/ASLayoutSpec.h index 4b583cb9fa..70914c4a41 100644 --- a/AsyncDisplayKit/Layout/ASLayoutSpec.h +++ b/AsyncDisplayKit/Layout/ASLayoutSpec.h @@ -63,19 +63,31 @@ NS_ASSUME_NONNULL_BEGIN @end /** - * An ASLayoutSpec subclass that can wrap a ASLayoutElement and calculates the layout of the child. + * An ASLayoutSpec subclass that can wrap one or more ASLayoutElement and calculates the layout based on the + * sizes of the children. If multiple children are provided the size of the biggest child will be used to for + * size of this layout spec. */ @interface ASWrapperLayoutSpec : ASLayoutSpec /* - * Returns an ASWrapperLayoutSpec object with the given layoutElement as child + * Returns an ASWrapperLayoutSpec object with the given layoutElement as child. */ + (instancetype)wrapperWithLayoutElement:(id)layoutElement AS_WARN_UNUSED_RESULT; /* - * Returns an ASWrapperLayoutSpec object initialized with the given layoutElement as child + * Returns an ASWrapperLayoutSpec object with the given layoutElements as children. */ -- (instancetype)initWithLayoutElement:(id)layoutElement NS_DESIGNATED_INITIALIZER; ++ (instancetype)wrapperWithLayoutElements:(NSArray> *)layoutElements AS_WARN_UNUSED_RESULT; + +/* + * Returns an ASWrapperLayoutSpec object initialized with the given layoutElement as child. + */ +- (instancetype)initWithLayoutElement:(id)layoutElement AS_WARN_UNUSED_RESULT; + +/* + * Returns an ASWrapperLayoutSpec object initialized with the given layoutElements as children. + */ +- (instancetype)initWithLayoutElements:(NSArray> *)layoutElements AS_WARN_UNUSED_RESULT; /* * Init not available for ASWrapperLayoutSpec diff --git a/AsyncDisplayKit/Layout/ASLayoutSpec.mm b/AsyncDisplayKit/Layout/ASLayoutSpec.mm index 3aa316aab2..b645b3c53b 100644 --- a/AsyncDisplayKit/Layout/ASLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASLayoutSpec.mm @@ -315,11 +315,36 @@ ASLayoutElementStyleForwarding return self; } ++ (instancetype)wrapperWithLayoutElements:(NSArray> *)layoutElements +{ + return [[self alloc] initWithLayoutElements:layoutElements]; +} + +- (instancetype)initWithLayoutElements:(NSArray> *)layoutElements +{ + self = [super init]; + if (self) { + self.children = layoutElements; + } + return self; +} + - (ASLayout *)calculateLayoutThatFits:(ASSizeRange)constrainedSize { - ASLayout *sublayout = [self.child layoutThatFits:constrainedSize parentSize:constrainedSize.max]; - sublayout.position = CGPointZero; - return [ASLayout layoutWithLayoutElement:self size:sublayout.size sublayouts:@[sublayout]]; + NSArray *children = self.children; + NSMutableArray *sublayouts = [NSMutableArray arrayWithCapacity:children.count]; + + CGSize size = constrainedSize.min; + for (id child in children) { + ASLayout *sublayout = [child layoutThatFits:constrainedSize parentSize:constrainedSize.max]; + + size.width = MAX(size.width, sublayout.size.width); + size.height = MAX(size.height, sublayout.size.height); + + [sublayouts addObject:sublayout]; + } + + return [ASLayout layoutWithLayoutElement:self size:size sublayouts:sublayouts]; } @end From f7b30577b8ba83189e47bfb05c1c77e2a19543aa Mon Sep 17 00:00:00 2001 From: Hannah Troisi Date: Mon, 24 Oct 2016 10:58:04 -0700 Subject: [PATCH 35/59] Pager Node Should Implement New ASCollectionDataSource/Delegate Methods (#2466) --- AsyncDisplayKit/ASPagerNode.m | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/AsyncDisplayKit/ASPagerNode.m b/AsyncDisplayKit/ASPagerNode.m index 909d1089dc..60eb520d58 100644 --- a/AsyncDisplayKit/ASPagerNode.m +++ b/AsyncDisplayKit/ASPagerNode.m @@ -14,7 +14,6 @@ #import "ASDelegateProxy.h" #import "ASDisplayNode+Subclasses.h" #import "ASPagerFlowLayout.h" -#import "ASCollectionView+Undeprecated.h" @interface ASPagerNode () { @@ -107,12 +106,12 @@ - (ASCellNode *)nodeForPageAtIndex:(NSInteger)index { - return [self.view nodeForItemAtIndexPath:[NSIndexPath indexPathForItem:index inSection:0]]; + return [self nodeForItemAtIndexPath:[NSIndexPath indexPathForItem:index inSection:0]]; } #pragma mark - ASCollectionDataSource -- (ASCellNodeBlock)collectionView:(ASCollectionView *)collectionView nodeBlockForItemAtIndexPath:(NSIndexPath *)indexPath +- (ASCellNodeBlock)collectionNode:(ASCollectionNode *)collectionNode nodeBlockForItemAtIndexPath:(NSIndexPath *)indexPath { ASDisplayNodeAssert(_pagerDataSource != nil, @"ASPagerNode must have a data source to load nodes to display"); if (!_pagerDataSourceImplementsNodeBlockAtIndex) { @@ -122,19 +121,19 @@ return [_pagerDataSource pagerNode:self nodeBlockAtIndex:indexPath.item]; } -- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section +- (NSInteger)collectionNode:(ASCollectionNode *)collectionNode numberOfItemsInSection:(NSInteger)section { ASDisplayNodeAssert(_pagerDataSource != nil, @"ASPagerNode must have a data source to load nodes to display"); return [_pagerDataSource numberOfPagesInPagerNode:self]; } -- (ASSizeRange)collectionView:(ASCollectionView *)collectionView constrainedSizeForNodeAtIndexPath:(NSIndexPath *)indexPath +- (ASSizeRange)collectionNode:(ASCollectionNode *)collectionNode constrainedSizeForItemAtIndexPath:(NSIndexPath *)indexPath { if (_pagerDelegateImplementsConstrainedSizeForNode) { return [_pagerDelegate pagerNode:self constrainedSizeForNodeAtIndex:indexPath.item]; } - return ASSizeRangeMake(CGSizeZero, self.view.bounds.size); + return ASSizeRangeMake(CGSizeZero, self.bounds.size); } #pragma mark - Data Source Proxy From 86a5aece9c48f070c103165ef4b6cff556e812a1 Mon Sep 17 00:00:00 2001 From: Garrett Moon Date: Mon, 24 Oct 2016 14:05:03 -0700 Subject: [PATCH 36/59] Caching scrollable directions is not safe (#2474) --- .../Details/ASCollectionViewLayoutController.mm | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/AsyncDisplayKit/Details/ASCollectionViewLayoutController.mm b/AsyncDisplayKit/Details/ASCollectionViewLayoutController.mm index 6672fb7b2a..14d1a0021e 100644 --- a/AsyncDisplayKit/Details/ASCollectionViewLayoutController.mm +++ b/AsyncDisplayKit/Details/ASCollectionViewLayoutController.mm @@ -30,7 +30,6 @@ typedef struct ASRangeGeometry ASRangeGeometry; @package ASCollectionView * __weak _collectionView; UICollectionViewLayout * __strong _collectionViewLayout; - ASScrollDirection _scrollableDirections; } @end @@ -42,7 +41,6 @@ typedef struct ASRangeGeometry ASRangeGeometry; return nil; } - _scrollableDirections = [collectionView scrollableDirections]; _collectionView = collectionView; _collectionViewLayout = [collectionView collectionViewLayout]; return self; @@ -74,12 +72,7 @@ typedef struct ASRangeGeometry ASRangeGeometry; { CGRect rect = _collectionView.bounds; - // Scrollable directions can change for non-flow layouts - if ([_collectionViewLayout asdk_isFlowLayout] == NO) { - _scrollableDirections = [_collectionView scrollableDirections]; - } - - return CGRectExpandToRangeWithScrollableDirections(rect, tuningParameters, _scrollableDirections, scrollDirection); + return CGRectExpandToRangeWithScrollableDirections(rect, tuningParameters, [_collectionView scrollableDirections], scrollDirection); } @end From 2834ba34906df71d01c741d08adba54ef20c77c0 Mon Sep 17 00:00:00 2001 From: Hannah Troisi Date: Mon, 24 Oct 2016 16:10:56 -0700 Subject: [PATCH 37/59] [ASPagerNode] Fix ASPagerNodeProxy to use collectionNode (#2475) * Fix ASProxyDelegate to use collectionNode * fix constrainedSize...issue --- AsyncDisplayKit/ASCollectionNode.h | 2 +- AsyncDisplayKit/ASPagerNode.m | 2 ++ AsyncDisplayKit/Details/ASDelegateProxy.m | 8 ++++---- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/AsyncDisplayKit/ASCollectionNode.h b/AsyncDisplayKit/ASCollectionNode.h index d5d799d68a..2e0c38cf97 100644 --- a/AsyncDisplayKit/ASCollectionNode.h +++ b/AsyncDisplayKit/ASCollectionNode.h @@ -593,7 +593,7 @@ NS_ASSUME_NONNULL_BEGIN * * @return A constrained size range for layout the node at this index path. */ -- (ASSizeRange)collectionView:(ASCollectionView *)collectionView constrainedSizeForNodeAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED_MSG("Use ASCollectionNode's method instead."); +- (ASSizeRange)collectionView:(ASCollectionView *)collectionView constrainedSizeForNodeAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED_MSG("Use ASCollectionNode's constrainedSizeForItemAtIndexPath: instead."); /** * Informs the delegate that the collection view will add the given node diff --git a/AsyncDisplayKit/ASPagerNode.m b/AsyncDisplayKit/ASPagerNode.m index 60eb520d58..0b42f2bc19 100644 --- a/AsyncDisplayKit/ASPagerNode.m +++ b/AsyncDisplayKit/ASPagerNode.m @@ -127,6 +127,8 @@ return [_pagerDataSource numberOfPagesInPagerNode:self]; } +#pragma mark - ASCollectionDelegate + - (ASSizeRange)collectionNode:(ASCollectionNode *)collectionNode constrainedSizeForItemAtIndexPath:(NSIndexPath *)indexPath { if (_pagerDelegateImplementsConstrainedSizeForNode) { diff --git a/AsyncDisplayKit/Details/ASDelegateProxy.m b/AsyncDisplayKit/Details/ASDelegateProxy.m index 460c50f0b6..38c32d2f49 100644 --- a/AsyncDisplayKit/Details/ASDelegateProxy.m +++ b/AsyncDisplayKit/Details/ASDelegateProxy.m @@ -116,10 +116,10 @@ { return ( // handled by ASPagerDataSource node<->cell machinery - selector == @selector(collectionView:nodeForItemAtIndexPath:) || - selector == @selector(collectionView:nodeBlockForItemAtIndexPath:) || - selector == @selector(collectionView:numberOfItemsInSection:) || - selector == @selector(collectionView:constrainedSizeForNodeAtIndexPath:) + selector == @selector(collectionNode:nodeForItemAtIndexPath:) || + selector == @selector(collectionNode:nodeBlockForItemAtIndexPath:) || + selector == @selector(collectionNode:numberOfItemsInSection:) || + selector == @selector(collectionNode:constrainedSizeForItemAtIndexPath:) ); } From 0d439a43b6eef8c720d28b5a93213074b827a7a6 Mon Sep 17 00:00:00 2001 From: Adlai Holler Date: Mon, 24 Oct 2016 17:05:59 -0700 Subject: [PATCH 38/59] [ASTextNode] Add Fast-Paths For Text Measurement and Drawing (#2392) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add test case for TextKit truncation style * Add fast path for text node measurement with default truncation * Use fast path more often * Reverse options order * Simplify implementation – no functional change * Share "isScaled" variable * Intersect with constrained rect * Add a failing test case for fast-path truncation * Add some more truncation tests, using slow path as reference image * Update the tests * In ASTextKitRenderer, intersect bounds with constrained rect * Add test case for TextKit truncation style * Add fast path for text node measurement with default truncation * Use fast path more often * Reverse options order * Simplify implementation – no functional change * Share "isScaled" variable * Intersect with constrained rect * Add a failing test case for fast-path truncation * Add some more truncation tests, using slow path as reference image * Update the tests * In ASTextKitRenderer, intersect bounds with constrained rect * Use maximumNumberOfLines property in text kit fast path Add reference images Disable fast-path for max-one-line case * Remove unneeded snapshot files --- AsyncDisplayKit/ASTextNode.mm | 2 +- AsyncDisplayKit/TextKit/ASTextKitRenderer.mm | 136 +++++++++++++----- AsyncDisplayKitTests/ASSnapshotTestCase.h | 3 + .../ASTextNodePerformanceTests.m | 2 +- .../ASTextNodeSnapshotTests.m | 19 ++- .../testThatFastPathTruncationWorks@2x.png | Bin 0 -> 4025 bytes .../testThatSlowPathTruncationWorks@2x.png | Bin 0 -> 4018 bytes .../testThatFastPathTruncationWorks@2x.png | Bin 0 -> 3978 bytes .../testThatSlowPathTruncationWorks@2x.png | Bin 0 -> 3974 bytes 9 files changed, 120 insertions(+), 42 deletions(-) create mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASTextNodeSnapshotTests/testThatFastPathTruncationWorks@2x.png create mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASTextNodeSnapshotTests/testThatSlowPathTruncationWorks@2x.png create mode 100644 AsyncDisplayKitTests/ReferenceImages_iOS_10/ASTextNodeSnapshotTests/testThatFastPathTruncationWorks@2x.png create mode 100644 AsyncDisplayKitTests/ReferenceImages_iOS_10/ASTextNodeSnapshotTests/testThatSlowPathTruncationWorks@2x.png diff --git a/AsyncDisplayKit/ASTextNode.mm b/AsyncDisplayKit/ASTextNode.mm index 3de201d87e..f287eb931f 100644 --- a/AsyncDisplayKit/ASTextNode.mm +++ b/AsyncDisplayKit/ASTextNode.mm @@ -1356,7 +1356,7 @@ static NSAttributedString *DefaultTruncationAttributedString() } // If we've reached this point, both _additionalTruncationMessage and - // _truncationAttributedString are present. Compose them. + // _truncationAttributedText are present. Compose them. NSMutableAttributedString *newComposedTruncationString = [[NSMutableAttributedString alloc] initWithAttributedString:_truncationAttributedText]; [newComposedTruncationString replaceCharactersInRange:NSMakeRange(newComposedTruncationString.length, 0) withString:@" "]; diff --git a/AsyncDisplayKit/TextKit/ASTextKitRenderer.mm b/AsyncDisplayKit/TextKit/ASTextKitRenderer.mm index 0beb67902c..4a6f5978c0 100755 --- a/AsyncDisplayKit/TextKit/ASTextKitRenderer.mm +++ b/AsyncDisplayKit/TextKit/ASTextKitRenderer.mm @@ -35,11 +35,20 @@ static NSCharacterSet *_defaultAvoidTruncationCharacterSet() return truncationCharacterSet; } +@interface ASTextKitRenderer() +/** + * This object is lazily created. It is provided to the NSAttributedString + * drawing methods used by the fast-paths in the size calculation and drawing + * instance methods. + */ +@property (nonatomic, strong, readonly) NSStringDrawingContext *stringDrawingContext; +@end + @implementation ASTextKitRenderer { CGSize _calculatedSize; BOOL _sizeIsCalculated; } -@synthesize attributes = _attributes, context = _context, shadower = _shadower, truncater = _truncater, fontSizeAdjuster = _fontSizeAdjuster; +@synthesize attributes = _attributes, context = _context, shadower = _shadower, truncater = _truncater, fontSizeAdjuster = _fontSizeAdjuster, stringDrawingContext = _stringDrawingContext; #pragma mark - Initialization @@ -50,6 +59,7 @@ static NSCharacterSet *_defaultAvoidTruncationCharacterSet() _constrainedSize = constrainedSize; _attributes = attributes; _sizeIsCalculated = NO; + _currentScaleFactor = 1; } return self; } @@ -106,6 +116,19 @@ static NSCharacterSet *_defaultAvoidTruncationCharacterSet() return _context; } +- (NSStringDrawingContext *)stringDrawingContext +{ + if (_stringDrawingContext == nil) { + _stringDrawingContext = [[NSStringDrawingContext alloc] init]; + + if (isinf(_constrainedSize.width) == NO && _attributes.maximumNumberOfLines > 0) { + ASDisplayNodeAssert(_attributes.maximumNumberOfLines != 1, @"Max line count 1 is not supported in fast-path."); + [_stringDrawingContext setValue:@(_attributes.maximumNumberOfLines) forKey:@"maximumNumberOfLines"]; + } + } + return _stringDrawingContext; +} + #pragma mark - Sizing - (CGSize)size @@ -144,9 +167,18 @@ static NSCharacterSet *_defaultAvoidTruncationCharacterSet() if (isinf(_constrainedSize.width) == NO && [_attributes.pointSizeScaleFactors count] > 0) { _currentScaleFactor = [[self fontSizeAdjuster] scaleFactor]; } - - __block NSTextStorage *scaledTextStorage = nil; + + // If we do not scale, do exclusion, or do custom truncation, we should just use NSAttributedString drawing for a fast-path. + if (self.canUseFastPath) { + CGRect rect = [_attributes.attributedString boundingRectWithSize:_constrainedSize options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingTruncatesLastVisibleLine context:self.stringDrawingContext]; + // Intersect with constrained rect, in case text kit goes out-of-bounds. + rect = CGRectIntersection(rect, {CGPointZero, _constrainedSize}); + _calculatedSize = [self.shadower outsetSizeWithInsetSize:rect.size]; + return; + } + BOOL isScaled = [self isScaled]; + __block NSTextStorage *scaledTextStorage = nil; if (isScaled) { // apply the string scale before truncating or else we may truncate the string after we've done the work to shrink it. [[self context] performBlockWithLockedTextKitComponents:^(NSLayoutManager *layoutManager, NSTextStorage *textStorage, NSTextContainer *textContainer) { @@ -161,15 +193,13 @@ static NSCharacterSet *_defaultAvoidTruncationCharacterSet() [[self truncater] truncate]; + CGRect constrainedRect = {CGPointZero, _constrainedSize}; + __block CGRect boundingRect; + // Force glyph generation and layout, which may not have happened yet (and isn't triggered by // -usedRectForTextContainer:). [[self context] performBlockWithLockedTextKitComponents:^(NSLayoutManager *layoutManager, NSTextStorage *textStorage, NSTextContainer *textContainer) { [layoutManager ensureLayoutForTextContainer:textContainer]; - }]; - - CGRect constrainedRect = {CGPointZero, _constrainedSize}; - __block CGRect boundingRect; - [[self context] performBlockWithLockedTextKitComponents:^(NSLayoutManager *layoutManager, NSTextStorage *textStorage, NSTextContainer *textContainer) { boundingRect = [layoutManager usedRectForTextContainer:textContainer]; if (isScaled) { // put the non-scaled version back @@ -181,13 +211,33 @@ static NSCharacterSet *_defaultAvoidTruncationCharacterSet() // TextKit often returns incorrect glyph bounding rects in the horizontal direction, so we clip to our bounding rect // to make sure our width calculations aren't being offset by glyphs going beyond the constrained rect. boundingRect = CGRectIntersection(boundingRect, {.size = constrainedRect.size}); - CGSize boundingSize = [_shadower outsetSizeWithInsetSize:boundingRect.size]; - _calculatedSize = CGSizeMake(boundingSize.width, boundingSize.height); + _calculatedSize = [_shadower outsetSizeWithInsetSize:boundingRect.size]; } - (BOOL)isScaled { - return (self.currentScaleFactor > 0 && self.currentScaleFactor < 1.0); + return (_currentScaleFactor > 0 && _currentScaleFactor < 1.0); +} + +- (BOOL)usesCustomTruncation +{ + // NOTE: This code does not correctly handle if they set `…` with different attributes. + return _attributes.avoidTailTruncationSet != nil || [_attributes.truncationAttributedString.string isEqualToString:@"\u2026"] == NO; +} + +- (BOOL)usesExclusionPaths +{ + return _attributes.exclusionPaths.count > 0; +} + +- (BOOL)canUseFastPath +{ + return self.isScaled == NO + && self.usesCustomTruncation == NO + && self.usesExclusionPaths == NO + // NSAttributedString drawing methods ignore usesLineFragmentOrigin if max line count 1, + // rendering them useless: + && (_attributes.maximumNumberOfLines != 1 || isinf(_constrainedSize.width)); } #pragma mark - Drawing @@ -198,11 +248,12 @@ static NSCharacterSet *_defaultAvoidTruncationCharacterSet() ASDisplayNodeAssertNotNil(context, @"This is no good without a context."); // This renderer may not be the one that did the sizing. If that is the case its truncation and currentScaleFactor may not have been evaluated. - // If there's any possibility we need to truncate or scale (e.g. width is not infinite, perform the size calculation. + // If there's any possibility we need to truncate or scale (i.e. width is not infinite), perform the size calculation. if (_sizeIsCalculated == NO && isinf(_constrainedSize.width) == NO) { [self _calculateSize]; } + bounds = CGRectIntersection(bounds, { .size = _constrainedSize }); CGRect shadowInsetBounds = [[self shadower] insetRectWithConstrainedRect:bounds]; CGContextSaveGState(context); @@ -210,35 +261,42 @@ static NSCharacterSet *_defaultAvoidTruncationCharacterSet() UIGraphicsPushContext(context); LOG(@"%@, shadowInsetBounds = %@",self, NSStringFromCGRect(shadowInsetBounds)); - - [[self context] performBlockWithLockedTextKitComponents:^(NSLayoutManager *layoutManager, NSTextStorage *textStorage, NSTextContainer *textContainer) { - - NSTextStorage *scaledTextStorage = nil; - BOOL isScaled = [self isScaled]; - if (isScaled) { - // if we are going to scale the text, swap out the non-scaled text for the scaled version. - NSMutableAttributedString *scaledString = [[NSMutableAttributedString alloc] initWithAttributedString:textStorage]; - [ASTextKitFontSizeAdjuster adjustFontSizeForAttributeString:scaledString withScaleFactor:_currentScaleFactor]; - scaledTextStorage = [[NSTextStorage alloc] initWithAttributedString:scaledString]; + // If we use default options, we can use NSAttributedString for a + // fast path. + if (self.canUseFastPath) { + [_attributes.attributedString drawWithRect:shadowInsetBounds options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingTruncatesLastVisibleLine context:self.stringDrawingContext]; + } else { + BOOL isScaled = [self isScaled]; + [[self context] performBlockWithLockedTextKitComponents:^(NSLayoutManager *layoutManager, NSTextStorage *textStorage, NSTextContainer *textContainer) { - [textStorage removeLayoutManager:layoutManager]; - [scaledTextStorage addLayoutManager:layoutManager]; - } - - LOG(@"usedRect: %@", NSStringFromCGRect([layoutManager usedRectForTextContainer:textContainer])); - NSRange glyphRange = [layoutManager glyphRangeForBoundingRect:CGRectMake(0,0,textContainer.size.width, textContainer.size.height) inTextContainer:textContainer]; - LOG(@"boundingRect: %@", NSStringFromCGRect([layoutManager boundingRectForGlyphRange:glyphRange inTextContainer:textContainer])); - - [layoutManager drawBackgroundForGlyphRange:glyphRange atPoint:shadowInsetBounds.origin]; - [layoutManager drawGlyphsForGlyphRange:glyphRange atPoint:shadowInsetBounds.origin]; - - if (isScaled) { - // put the non-scaled version back - [scaledTextStorage removeLayoutManager:layoutManager]; - [textStorage addLayoutManager:layoutManager]; - } - }]; + NSTextStorage *scaledTextStorage = nil; + + if (isScaled) { + // if we are going to scale the text, swap out the non-scaled text for the scaled version. + NSMutableAttributedString *scaledString = [[NSMutableAttributedString alloc] initWithAttributedString:textStorage]; + [ASTextKitFontSizeAdjuster adjustFontSizeForAttributeString:scaledString withScaleFactor:_currentScaleFactor]; + scaledTextStorage = [[NSTextStorage alloc] initWithAttributedString:scaledString]; + + [textStorage removeLayoutManager:layoutManager]; + [scaledTextStorage addLayoutManager:layoutManager]; + } + + LOG(@"usedRect: %@", NSStringFromCGRect([layoutManager usedRectForTextContainer:textContainer])); + + NSRange glyphRange = [layoutManager glyphRangeForBoundingRect:CGRectMake(0,0,textContainer.size.width, textContainer.size.height) inTextContainer:textContainer]; + LOG(@"boundingRect: %@", NSStringFromCGRect([layoutManager boundingRectForGlyphRange:glyphRange inTextContainer:textContainer])); + + [layoutManager drawBackgroundForGlyphRange:glyphRange atPoint:shadowInsetBounds.origin]; + [layoutManager drawGlyphsForGlyphRange:glyphRange atPoint:shadowInsetBounds.origin]; + + if (isScaled) { + // put the non-scaled version back + [scaledTextStorage removeLayoutManager:layoutManager]; + [textStorage addLayoutManager:layoutManager]; + } + }]; + } UIGraphicsPopContext(); CGContextRestoreGState(context); diff --git a/AsyncDisplayKitTests/ASSnapshotTestCase.h b/AsyncDisplayKitTests/ASSnapshotTestCase.h index 977e267d17..c89fc79af4 100644 --- a/AsyncDisplayKitTests/ASSnapshotTestCase.h +++ b/AsyncDisplayKitTests/ASSnapshotTestCase.h @@ -29,6 +29,9 @@ NSOrderedSet *ASSnapshotTestCaseDefaultSuffixes(void); #define ASSnapshotVerifyLayer(layer__, identifier__) \ FBSnapshotVerifyLayerWithOptions(layer__, identifier__, ASSnapshotTestCaseDefaultSuffixes(), 0); +#define ASSnapshotVerifyView(view__, identifier__) \ + FBSnapshotVerifyViewWithOptions(view__, identifier__, ASSnapshotTestCaseDefaultSuffixes(), 0); + @interface ASSnapshotTestCase : FBSnapshotTestCase /** diff --git a/AsyncDisplayKitTests/ASTextNodePerformanceTests.m b/AsyncDisplayKitTests/ASTextNodePerformanceTests.m index 9ed8f1ea0c..d3a0fa50e8 100644 --- a/AsyncDisplayKitTests/ASTextNodePerformanceTests.m +++ b/AsyncDisplayKitTests/ASTextNodePerformanceTests.m @@ -108,7 +108,7 @@ static NSString *const kTestCaseUIKitWithReusedContext = @"UIKitReusedContext"; ctx.results[kTestCaseASDK].userInfo[@"size"] = NSStringFromCGSize(asdkSize); ASXCTAssertEqualSizes(uiKitSize, asdkSize); - ASXCTAssertRelativePerformanceInRange(ctx, kTestCaseASDK, 0.2, 0.5); + ASXCTAssertRelativePerformanceInRange(ctx, kTestCaseASDK, 0.5, 0.9); } - (void)testPerformance_OneParagraphLatinWithTruncation diff --git a/AsyncDisplayKitTests/ASTextNodeSnapshotTests.m b/AsyncDisplayKitTests/ASTextNodeSnapshotTests.m index 895f1841af..08b953374d 100644 --- a/AsyncDisplayKitTests/ASTextNodeSnapshotTests.m +++ b/AsyncDisplayKitTests/ASTextNodeSnapshotTests.m @@ -72,7 +72,24 @@ textNode.highlightRange = NSMakeRange(0, textNode.attributedText.length); [ASSnapshotTestCase hackilySynchronouslyRecursivelyRenderNode:textNode]; - ASSnapshotVerifyLayer(backgroundView.layer, nil); + ASSnapshotVerifyView(backgroundView, nil); +} + +- (void)testThatFastPathTruncationWorks +{ + ASTextNode *textNode = [[ASTextNode alloc] init]; + textNode.attributedText = [[NSAttributedString alloc] initWithString:@"Quality is Important" attributes:@{ NSForegroundColorAttributeName: [UIColor blueColor], NSFontAttributeName: [UIFont italicSystemFontOfSize:24] }]; + [textNode layoutThatFits:ASSizeRangeMake(CGSizeZero, CGSizeMake(100, 50))]; + ASSnapshotVerifyNode(textNode, nil); +} + +- (void)testThatSlowPathTruncationWorks +{ + ASTextNode *textNode = [[ASTextNode alloc] init]; + textNode.attributedText = [[NSAttributedString alloc] initWithString:@"Quality is Important" attributes:@{ NSForegroundColorAttributeName: [UIColor blueColor], NSFontAttributeName: [UIFont italicSystemFontOfSize:24] }]; + [textNode layoutThatFits:ASSizeRangeMake(CGSizeZero, CGSizeMake(100, 50))]; + textNode.exclusionPaths = @[ [UIBezierPath bezierPath] ]; + ASSnapshotVerifyNode(textNode, nil); } @end diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASTextNodeSnapshotTests/testThatFastPathTruncationWorks@2x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASTextNodeSnapshotTests/testThatFastPathTruncationWorks@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d9f01fce31cece0c0d98b6dbb7ad2361a1e31499 GIT binary patch literal 4025 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 literal 0 HcmV?d00001 diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASTextNodeSnapshotTests/testThatSlowPathTruncationWorks@2x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASTextNodeSnapshotTests/testThatSlowPathTruncationWorks@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..dcae0039092c3ce3d71e5010f4d64442ad92bf72 GIT binary patch literal 4018 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 N0H$rMRiW$|M_TI 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 YrfUp-(iti}{6bhNN*apQ@|I!$1K%os`2YX_ literal 0 HcmV?d00001 diff --git a/AsyncDisplayKitTests/ReferenceImages_iOS_10/ASTextNodeSnapshotTests/testThatSlowPathTruncationWorks@2x.png b/AsyncDisplayKitTests/ReferenceImages_iOS_10/ASTextNodeSnapshotTests/testThatSlowPathTruncationWorks@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..bf816c2ed4b7818599b00b5f06df29c7f770d53e GIT binary patch literal 3974 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 Z3yT^ndU;-(+dqg%Ps>QN`mr Date: Mon, 24 Oct 2016 17:14:28 -0700 Subject: [PATCH 39/59] [Examples] 2.0 Collection/Table API updates (#2390) * update VerticalWithinHorizontal example * update SocialAppLayout * update Kittens * update HorizontalWithinVerticalScrolling * update AsyncDisplayKitOverview * update CustomCollectionView * CatDealsCollectionView * update Swift * address @appleguy's comment * updates for tableNode deselectRowAtIndexPath --- .../ASViewController/Sample/ViewController.m | 2 +- .../OverviewASCollectionNode.m | 6 +- .../Node Containers/OverviewASTableNode.m | 4 +- .../Sample/OverviewComponentsViewController.h | 4 +- .../Sample/OverviewComponentsViewController.m | 54 ++++++--- .../Sample/ViewController.m | 114 ++++++++---------- .../CustomCollectionView/Sample/AppDelegate.m | 2 +- .../Sample/ViewController.m | 34 +++--- .../Sample/HorizontalScrollCellNode.mm | 71 +++++------ .../Sample/ViewController.m | 14 +-- examples/Kittens/Sample/ViewController.h | 4 +- examples/Kittens/Sample/ViewController.m | 106 ++++++++-------- .../SocialAppLayout/Sample/ViewController.h | 4 +- .../SocialAppLayout/Sample/ViewController.m | 48 ++++---- examples/Swift/Sample/ViewController.swift | 60 ++++----- .../Sample/GradientTableNode.h | 2 +- .../Sample/GradientTableNode.mm | 34 +++--- 17 files changed, 275 insertions(+), 288 deletions(-) diff --git a/examples/ASViewController/Sample/ViewController.m b/examples/ASViewController/Sample/ViewController.m index b7014b6c8c..2b3cb1d229 100644 --- a/examples/ASViewController/Sample/ViewController.m +++ b/examples/ASViewController/Sample/ViewController.m @@ -66,7 +66,7 @@ { [super viewWillAppear:animated]; - [self.tableNode.view deselectRowAtIndexPath:self.tableNode.view.indexPathForSelectedRow animated:YES]; + [self.tableNode deselectRowAtIndexPath:self.tableNode.view.indexPathForSelectedRow animated:YES]; } diff --git a/examples/AsyncDisplayKitOverview/Sample/Node Containers/OverviewASCollectionNode.m b/examples/AsyncDisplayKitOverview/Sample/Node Containers/OverviewASCollectionNode.m index d58b6862a5..78c8615ede 100644 --- a/examples/AsyncDisplayKitOverview/Sample/Node Containers/OverviewASCollectionNode.m +++ b/examples/AsyncDisplayKitOverview/Sample/Node Containers/OverviewASCollectionNode.m @@ -53,12 +53,12 @@ #pragma mark - -- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section +- (NSInteger)collectionNode:(ASCollectionNode *)collectionNode numberOfItemsInSection:(NSInteger)section { return 100; } -- (ASCellNodeBlock)collectionView:(ASCollectionView *)collectionView nodeBlockForItemAtIndexPath:(NSIndexPath *)indexPath +- (ASCellNodeBlock)collectionNode:(ASCollectionNode *)collectionNode nodeBlockForItemAtIndexPath:(NSIndexPath *)indexPath { return ^{ ASTextCellNode *cellNode = [ASTextCellNode new]; @@ -68,7 +68,7 @@ }; } -- (ASSizeRange)collectionView:(ASCollectionView *)collectionView constrainedSizeForNodeAtIndexPath:(NSIndexPath *)indexPath +- (ASSizeRange)collectionNode:(ASCollectionNode *)collectionNode constrainedSizeForItemAtIndexPath:(NSIndexPath *)indexPath { return ASSizeRangeMake(CGSizeMake(100, 100)); } diff --git a/examples/AsyncDisplayKitOverview/Sample/Node Containers/OverviewASTableNode.m b/examples/AsyncDisplayKitOverview/Sample/Node Containers/OverviewASTableNode.m index 3d1e65ddba..1a94fdbf84 100644 --- a/examples/AsyncDisplayKitOverview/Sample/Node Containers/OverviewASTableNode.m +++ b/examples/AsyncDisplayKitOverview/Sample/Node Containers/OverviewASTableNode.m @@ -51,12 +51,12 @@ #pragma mark - -- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section +- (NSInteger)tableNode:(ASTableNode *)tableNode numberOfRowsInSection:(NSInteger)section { return 100; } -- (ASCellNodeBlock)tableView:(ASTableView *)tableView nodeBlockForRowAtIndexPath:(NSIndexPath *)indexPath +- (ASCellNodeBlock)tableNode:(ASTableNode *)tableNode nodeBlockForRowAtIndexPath:(NSIndexPath *)indexPath { return ^{ ASTextCellNode *cellNode = [ASTextCellNode new]; diff --git a/examples/AsyncDisplayKitOverview/Sample/OverviewComponentsViewController.h b/examples/AsyncDisplayKitOverview/Sample/OverviewComponentsViewController.h index 880cf78a58..9e838b4fba 100644 --- a/examples/AsyncDisplayKitOverview/Sample/OverviewComponentsViewController.h +++ b/examples/AsyncDisplayKitOverview/Sample/OverviewComponentsViewController.h @@ -17,7 +17,7 @@ // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -#import +#import @protocol ASLayoutSpecListEntry @@ -27,7 +27,7 @@ @end -@interface OverviewComponentsViewController : UIViewController +@interface OverviewComponentsViewController : ASViewController @end diff --git a/examples/AsyncDisplayKitOverview/Sample/OverviewComponentsViewController.m b/examples/AsyncDisplayKitOverview/Sample/OverviewComponentsViewController.m index 585c4c35f2..c343d74a65 100644 --- a/examples/AsyncDisplayKitOverview/Sample/OverviewComponentsViewController.m +++ b/examples/AsyncDisplayKitOverview/Sample/OverviewComponentsViewController.m @@ -31,12 +31,15 @@ typedef ASLayoutSpec *(^OverviewDisplayNodeSizeThatFitsBlock)(ASSizeRange constrainedSize); + #pragma mark - OverviewDisplayNodeWithSizeBlock @interface OverviewDisplayNodeWithSizeBlock : ASDisplayNode + @property (nonatomic, copy) NSString *entryTitle; @property (nonatomic, copy) NSString *entryDescription; @property (nonatomic, copy) OverviewDisplayNodeSizeThatFitsBlock sizeThatFitsBlock; + @end @implementation OverviewDisplayNodeWithSizeBlock @@ -54,11 +57,14 @@ typedef ASLayoutSpec *(^OverviewDisplayNodeSizeThatFitsBlock)(ASSizeRange constr @end + #pragma mark - OverviewTitleDescriptionCellNode @interface OverviewTitleDescriptionCellNode : ASCellNode + @property (nonatomic, strong) ASTextNode *titleNode; @property (nonatomic, strong) ASTextNode *descriptionNode; + @end @implementation OverviewTitleDescriptionCellNode @@ -91,16 +97,35 @@ typedef ASLayoutSpec *(^OverviewDisplayNodeSizeThatFitsBlock)(ASSizeRange constr @end + #pragma mark - OverviewComponentsViewController @interface OverviewComponentsViewController () + @property (nonatomic, copy) NSArray *data; @property (nonatomic, strong) ASTableNode *tableNode; + @end @implementation OverviewComponentsViewController -#pragma mark - UIViewController + +#pragma mark - Lifecycle Methods + +- (instancetype)init +{ + _tableNode = [ASTableNode new]; + + self = [super initWithNode:_tableNode]; + + if (self) { + _tableNode.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + _tableNode.delegate = (id)self; + _tableNode.dataSource = (id)self; + } + + return self; +} - (void)viewDidLoad { @@ -109,18 +134,17 @@ typedef ASLayoutSpec *(^OverviewDisplayNodeSizeThatFitsBlock)(ASSizeRange constr self.title = @"AsyncDisplayKit"; [self setupData]; - [self setupTableNode]; } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; - ASTableView *tableView = self.tableNode.view; - [tableView deselectRowAtIndexPath:tableView.indexPathForSelectedRow animated:YES]; + [_tableNode deselectRowAtIndexPath:_tableNode.view.indexPathForSelectedRow animated:YES]; } -#pragma mark - Setup + +#pragma mark - Data Model - (void)setupData { @@ -452,16 +476,6 @@ typedef ASLayoutSpec *(^OverviewDisplayNodeSizeThatFitsBlock)(ASSizeRange constr self.data = mutableData; } -- (void)setupTableNode -{ - _tableNode = [ASTableNode new]; - _tableNode.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; - _tableNode.frame = self.view.bounds; - _tableNode.delegate = (id)self; - _tableNode.dataSource = (id)self; - [self.view addSubnode:_tableNode]; -} - #pragma mark - Parent / Child Helper - (OverviewDisplayNodeWithSizeBlock *)parentNodeWithChild:(ASDisplayNode *)child @@ -505,22 +519,22 @@ typedef ASLayoutSpec *(^OverviewDisplayNodeSizeThatFitsBlock)(ASSizeRange constr #pragma mark - -- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView +- (NSInteger)numberOfSectionsInTableNode:(ASTableNode *)tableNode { return self.data.count; } -- (nullable NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section +- (nullable NSString *)tableNode:(ASTableNode *)tableNode titleForHeaderInSection:(NSInteger)section { return self.data[section][@"title"]; } -- (NSInteger)tableView:(ASTableView *)tableView numberOfRowsInSection:(NSInteger)section +- (NSInteger)tableNode:(ASTableNode *)tableNode numberOfRowsInSection:(NSInteger)section { return [self.data[section][@"data"] count]; } -- (ASCellNodeBlock)tableView:(ASTableView *)tableView nodeBlockForRowAtIndexPath:(NSIndexPath *)indexPath +- (ASCellNodeBlock)tableNode:(ASTableNode *)tableNode nodeBlockForRowAtIndexPath:(NSIndexPath *)indexPath { // You should get the node or data you want to pass to the cell node outside of the ASCellNodeBlock ASDisplayNode *node = self.data[indexPath.section][@"data"][indexPath.row]; @@ -542,7 +556,7 @@ typedef ASLayoutSpec *(^OverviewDisplayNodeSizeThatFitsBlock)(ASSizeRange constr }; } -- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath +- (void)tableNode:(ASTableNode *)tableNode didSelectRowAtIndexPath:(NSIndexPath *)indexPath { ASDisplayNode *node = self.data[indexPath.section][@"data"][indexPath.row]; OverviewDetailViewController *detail = [[OverviewDetailViewController alloc] initWithNode:node]; diff --git a/examples/CatDealsCollectionView/Sample/ViewController.m b/examples/CatDealsCollectionView/Sample/ViewController.m index 4cec349673..8726968ef4 100644 --- a/examples/CatDealsCollectionView/Sample/ViewController.m +++ b/examples/CatDealsCollectionView/Sample/ViewController.m @@ -29,7 +29,7 @@ static const NSInteger kBatchSize = 20; static const CGFloat kHorizontalSectionPadding = 10.0f; static const CGFloat kVerticalSectionPadding = 20.0f; -@interface ViewController () +@interface ViewController () { ASCollectionNode *_collectionNode; NSMutableArray *_data; @@ -45,15 +45,15 @@ static const CGFloat kVerticalSectionPadding = 20.0f; - (instancetype)init { + UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init]; + _collectionNode = [[ASCollectionNode alloc] initWithCollectionViewLayout:layout]; + self = [super initWithNode:_collectionNode]; if (self) { self.title = @"Cat Deals"; - - UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init]; - - _collectionNode = [[ASCollectionNode alloc] initWithCollectionViewLayout:layout]; + _collectionNode.dataSource = self; _collectionNode.delegate = self; _collectionNode.backgroundColor = [UIColor grayColor]; @@ -63,10 +63,10 @@ static const CGFloat kVerticalSectionPadding = 20.0f; preloadTuning.trailingBufferScreenfuls = 1; [_collectionNode setTuningParameters:preloadTuning forRangeType:ASLayoutRangeTypePreload]; - ASRangeTuningParameters preRenderTuning; - preRenderTuning.leadingBufferScreenfuls = 1; - preRenderTuning.trailingBufferScreenfuls = 0.5; - [_collectionNode setTuningParameters:preRenderTuning forRangeType:ASLayoutRangeTypeDisplay]; + ASRangeTuningParameters displayTuning; + displayTuning.leadingBufferScreenfuls = 1; + displayTuning.trailingBufferScreenfuls = 0.5; + [_collectionNode setTuningParameters:displayTuning forRangeType:ASLayoutRangeTypeDisplay]; [_collectionNode registerSupplementaryNodeOfKind:UICollectionElementKindSectionHeader]; [_collectionNode registerSupplementaryNodeOfKind:UICollectionElementKindSectionFooter]; @@ -151,10 +151,9 @@ static const CGFloat kVerticalSectionPadding = 20.0f; [_collectionNode reloadData]; } -#pragma mark - -#pragma mark ASCollectionView data source. +#pragma mark - ASCollectionNodeDelegate / ASCollectionNodeDataSource -- (ASCellNodeBlock)collectionView:(ASCollectionView *)collectionView nodeBlockForItemAtIndexPath:(NSIndexPath *)indexPath +- (ASCellNodeBlock)collectionNode:(ASCollectionNode *)collectionNode nodeBlockForItemAtIndexPath:(NSIndexPath *)indexPath { ItemViewModel *viewModel = _data[indexPath.item]; return ^{ @@ -162,7 +161,8 @@ static const CGFloat kVerticalSectionPadding = 20.0f; }; } -- (ASCellNode *)collectionView:(UICollectionView *)collectionView nodeForSupplementaryElementOfKind:(nonnull NSString *)kind atIndexPath:(nonnull NSIndexPath *)indexPath { +- (ASCellNode *)collectionNode:(ASCollectionNode *)collectionNode nodeForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath +{ if ([kind isEqualToString:UICollectionElementKindSectionHeader] && indexPath.section == 0) { return [[BlurbNode alloc] init]; } else if ([kind isEqualToString:UICollectionElementKindSectionFooter] && indexPath.section == 0) { @@ -171,6 +171,44 @@ static const CGFloat kVerticalSectionPadding = 20.0f; return nil; } +- (ASSizeRange)collectionNode:(ASCollectionNode *)collectionNode constrainedSizeForItemAtIndexPath:(NSIndexPath *)indexPath +{ + CGFloat collectionViewWidth = CGRectGetWidth(self.view.frame) - 2 * kHorizontalSectionPadding; + CGFloat oneItemWidth = [ItemNode preferredViewSize].width; + NSInteger numColumns = floor(collectionViewWidth / oneItemWidth); + // Number of columns should be at least 1 + numColumns = MAX(1, numColumns); + + CGFloat totalSpaceBetweenColumns = (numColumns - 1) * kHorizontalSectionPadding; + CGFloat itemWidth = ((collectionViewWidth - totalSpaceBetweenColumns) / numColumns); + CGSize itemSize = [ItemNode sizeForWidth:itemWidth]; + return ASSizeRangeMake(itemSize, itemSize); +} + +- (NSInteger)collectionNode:(ASCollectionNode *)collectionNode numberOfItemsInSection:(NSInteger)section +{ + return [_data count]; +} + +- (NSInteger)numberOfSectionsInCollectionNode:(ASCollectionNode *)collectionNode +{ + return 1; +} + +- (void)collectionNode:(ASCollectionNode *)collectionNode willBeginBatchFetchWithContext:(ASBatchContext *)context +{ + NSLog(@"fetch additional content"); + [self fetchMoreCatsWithCompletion:^(BOOL finished){ + [context completeBatchFetching:YES]; + }]; +} + +#pragma mark - ASCollectionViewDelegateFlowLayout + +- (UIEdgeInsets)collectionView:(ASCollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section { + return UIEdgeInsetsMake(kVerticalSectionPadding, kHorizontalSectionPadding, kVerticalSectionPadding, kHorizontalSectionPadding); +} + - (CGSize)collectionView:(ASCollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section { if (section == 0) { CGFloat width = CGRectGetWidth(self.view.frame) - 2 * kHorizontalSectionPadding; @@ -187,55 +225,5 @@ static const CGFloat kVerticalSectionPadding = 20.0f; return CGSizeZero; } -- (ASSizeRange)collectionView:(ASCollectionView *)collectionView constrainedSizeForNodeAtIndexPath:(NSIndexPath *)indexPath { - CGFloat collectionViewWidth = CGRectGetWidth(self.view.frame) - 2 * kHorizontalSectionPadding; - CGFloat oneItemWidth = [ItemNode preferredViewSize].width; - NSInteger numColumns = floor(collectionViewWidth / oneItemWidth); - // Number of columns should be at least 1 - numColumns = MAX(1, numColumns); - - CGFloat totalSpaceBetweenColumns = (numColumns - 1) * kHorizontalSectionPadding; - CGFloat itemWidth = ((collectionViewWidth - totalSpaceBetweenColumns) / numColumns); - CGSize itemSize = [ItemNode sizeForWidth:itemWidth]; - return ASSizeRangeMake(itemSize, itemSize); -} - -- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section -{ - return [_data count]; -} - -- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView -{ - return 1; -} - -- (void)collectionViewLockDataSource:(ASCollectionView *)collectionView -{ - // lock the data source - // The data source should not be change until it is unlocked. -} - -- (void)collectionViewUnlockDataSource:(ASCollectionView *)collectionView -{ - // unlock the data source to enable data source updating. -} - -- (void)collectionView:(UICollectionView *)collectionView willBeginBatchFetchWithContext:(ASBatchContext *)context -{ - NSLog(@"fetch additional content"); - [self fetchMoreCatsWithCompletion:^(BOOL finished){ - [context completeBatchFetching:YES]; - }]; -} - -- (UIEdgeInsets)collectionView:(ASCollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section { - return UIEdgeInsetsMake(kVerticalSectionPadding, kHorizontalSectionPadding, kVerticalSectionPadding, kHorizontalSectionPadding); -} - --(void)dealloc -{ - NSLog(@"ViewController is deallocing"); -} @end diff --git a/examples/CustomCollectionView/Sample/AppDelegate.m b/examples/CustomCollectionView/Sample/AppDelegate.m index 853bf6e8bc..c0769e5d5a 100644 --- a/examples/CustomCollectionView/Sample/AppDelegate.m +++ b/examples/CustomCollectionView/Sample/AppDelegate.m @@ -26,7 +26,7 @@ self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; self.window.backgroundColor = [UIColor whiteColor]; self.window.rootViewController = [[ViewController alloc] init]; - + [self.window makeKeyAndVisible]; return YES; diff --git a/examples/CustomCollectionView/Sample/ViewController.m b/examples/CustomCollectionView/Sample/ViewController.m index a7fe524811..5d070ebcd6 100644 --- a/examples/CustomCollectionView/Sample/ViewController.m +++ b/examples/CustomCollectionView/Sample/ViewController.m @@ -39,6 +39,17 @@ static NSUInteger kNumberOfImages = 14; - (instancetype)init { + MosaicCollectionViewLayout *layout = [[MosaicCollectionViewLayout alloc] init]; + layout.numberOfColumns = 2; + layout.headerHeight = 44.0; + + _collectionNode = [[ASCollectionNode alloc] initWithCollectionViewLayout:layout]; + _collectionNode.dataSource = self; + _collectionNode.delegate = self; + _collectionNode.backgroundColor = [UIColor whiteColor]; + + _layoutInspector = [[MosaicCollectionViewLayoutInspector alloc] init]; + if (!(self = [super initWithNode:_collectionNode])) return nil; @@ -53,16 +64,6 @@ static NSUInteger kNumberOfImages = 14; } } - MosaicCollectionViewLayout *layout = [[MosaicCollectionViewLayout alloc] init]; - layout.numberOfColumns = 2; - layout.headerHeight = 44.0; - - _layoutInspector = [[MosaicCollectionViewLayoutInspector alloc] init]; - - _collectionNode.dataSource = self; - _collectionNode.delegate = self; - _collectionNode.backgroundColor = [UIColor whiteColor]; - [_collectionNode registerSupplementaryNodeOfKind:UICollectionElementKindSectionHeader]; return self; @@ -75,19 +76,12 @@ static NSUInteger kNumberOfImages = 14; _collectionNode.view.layoutInspector = _layoutInspector; } -- (void)dealloc -{ - _collectionNode.dataSource = nil; - _collectionNode.delegate = nil; -} - - (void)reloadTapped { [_collectionNode reloadData]; } -#pragma mark - -#pragma mark ASCollectionView data source. +#pragma mark - ASCollectionNode data source. - (ASCellNodeBlock)collectionNode:(ASCollectionNode *)collectionNode nodeBlockForItemAtIndexPath:(NSIndexPath *)indexPath { @@ -110,12 +104,12 @@ static NSUInteger kNumberOfImages = 14; return textCellNode; } -- (NSInteger)numberOfSectionsInCollectionView:(ASCollectionNode *)collectionNode +- (NSInteger)numberOfSectionsInCollectionNode:(ASCollectionNode *)collectionNode { return _sections.count; } -- (NSInteger)collectionView:(ASCollectionNode *)collectionNode numberOfItemsInSection:(NSInteger)section +- (NSInteger)collectionNode:(ASCollectionNode *)collectionNode numberOfItemsInSection:(NSInteger)section { return [_sections[section] count]; } diff --git a/examples/HorizontalWithinVerticalScrolling/Sample/HorizontalScrollCellNode.mm b/examples/HorizontalWithinVerticalScrolling/Sample/HorizontalScrollCellNode.mm index e070c4fbe9..9f2f355e9a 100644 --- a/examples/HorizontalWithinVerticalScrolling/Sample/HorizontalScrollCellNode.mm +++ b/examples/HorizontalWithinVerticalScrolling/Sample/HorizontalScrollCellNode.mm @@ -39,6 +39,8 @@ static const CGFloat kInnerPadding = 10.0f; @implementation HorizontalScrollCellNode +#pragma mark - Lifecycle + - (instancetype)initWithElementSize:(CGSize)size { if (!(self = [super init])) @@ -46,11 +48,16 @@ static const CGFloat kInnerPadding = 10.0f; _elementSize = size; + // the containing table uses -nodeForRowAtIndexPath (rather than -nodeBlockForRowAtIndexPath), + // so this init method will always be run on the main thread (thus it is safe to do UIKit things). UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init]; flowLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal; flowLayout.itemSize = _elementSize; flowLayout.minimumInteritemSpacing = kInnerPadding; + _collectionNode = [[ASCollectionNode alloc] initWithCollectionViewLayout:flowLayout]; + _collectionNode.delegate = self; + _collectionNode.dataSource = self; [self addSubnode:_collectionNode]; // hairline cell separator @@ -61,40 +68,6 @@ static const CGFloat kInnerPadding = 10.0f; return self; } -- (void)didLoad -{ - [super didLoad]; - - _collectionNode.view.asyncDelegate = self; - _collectionNode.view.asyncDataSource = self; -} - -- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section -{ - return 5; -} - -- (ASCellNodeBlock)collectionView:(ASCollectionView *)collectionView nodeBlockForItemAtIndexPath:(NSIndexPath *)indexPath -{ - CGSize elementSize = _elementSize; - return ^{ - RandomCoreGraphicsNode *elementNode = [[RandomCoreGraphicsNode alloc] init]; - elementNode.style.preferredSize = elementSize; - return elementNode; - }; -} - -- (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize -{ - CGSize collectionNodeSize = CGSizeMake(constrainedSize.max.width, _elementSize.height); - _collectionNode.style.preferredSize = collectionNodeSize; - - ASInsetLayoutSpec *insetSpec = [[ASInsetLayoutSpec alloc] init]; - insetSpec.insets = UIEdgeInsetsMake(kOuterPadding, 0.0, kOuterPadding, 0.0); - insetSpec.child = _collectionNode; - return insetSpec; -} - // With box model, you don't need to override this method, unless you want to add custom logic. - (void)layout { @@ -107,4 +80,34 @@ static const CGFloat kInnerPadding = 10.0f; _divider.frame = CGRectMake(0.0f, 0.0f, self.calculatedSize.width, pixelHeight); } +- (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize +{ + CGSize collectionNodeSize = CGSizeMake(constrainedSize.max.width, _elementSize.height); + _collectionNode.style.preferredSize = collectionNodeSize; + + ASInsetLayoutSpec *insetSpec = [[ASInsetLayoutSpec alloc] init]; + insetSpec.insets = UIEdgeInsetsMake(kOuterPadding, 0.0, kOuterPadding, 0.0); + insetSpec.child = _collectionNode; + + return insetSpec; +} + +#pragma mark - ASCollectionNode + +- (NSInteger)collectionNode:(ASCollectionNode *)collectionNode numberOfItemsInSection:(NSInteger)section +{ + return 5; +} + +- (ASCellNodeBlock)collectionNode:(ASCollectionNode *)collectionNode nodeBlockForItemAtIndexPath:(NSIndexPath *)indexPath +{ + CGSize elementSize = _elementSize; + + return ^{ + RandomCoreGraphicsNode *elementNode = [[RandomCoreGraphicsNode alloc] init]; + elementNode.style.preferredSize = elementSize; + return elementNode; + }; +} + @end diff --git a/examples/HorizontalWithinVerticalScrolling/Sample/ViewController.m b/examples/HorizontalWithinVerticalScrolling/Sample/ViewController.m index 56ba5e22ab..876775f35c 100644 --- a/examples/HorizontalWithinVerticalScrolling/Sample/ViewController.m +++ b/examples/HorizontalWithinVerticalScrolling/Sample/ViewController.m @@ -34,13 +34,13 @@ - (instancetype)init { - if (!(self = [super initWithNode:_tableNode])) - return nil; - _tableNode = [[ASTableNode alloc] initWithStyle:UITableViewStylePlain]; _tableNode.dataSource = self; _tableNode.delegate = self; - + + if (!(self = [super initWithNode:_tableNode])) + return nil; + self.title = @"Horizontal Scrolling Gradients"; self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRedo target:self @@ -61,14 +61,14 @@ [_tableNode reloadData]; } -#pragma mark - ASTableView. +#pragma mark - ASTableNode -- (ASCellNode *)tableView:(ASTableView *)tableView nodeForRowAtIndexPath:(NSIndexPath *)indexPath +- (ASCellNode *)tableNode:(ASTableNode *)tableNode nodeForRowAtIndexPath:(NSIndexPath *)indexPath { return [[HorizontalScrollCellNode alloc] initWithElementSize:CGSizeMake(100, 100)]; } -- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section +- (NSInteger)tableNode:(ASTableNode *)tableNode numberOfRowsInSection:(NSInteger)section { return 100; } diff --git a/examples/Kittens/Sample/ViewController.h b/examples/Kittens/Sample/ViewController.h index fc52c022f2..db689fe324 100644 --- a/examples/Kittens/Sample/ViewController.h +++ b/examples/Kittens/Sample/ViewController.h @@ -15,8 +15,8 @@ // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -#import +#import -@interface ViewController : UIViewController +@interface ViewController : ASViewController @end diff --git a/examples/Kittens/Sample/ViewController.m b/examples/Kittens/Sample/ViewController.m index b4f0ad01b0..6b2e4b5058 100644 --- a/examples/Kittens/Sample/ViewController.m +++ b/examples/Kittens/Sample/ViewController.m @@ -24,13 +24,13 @@ #import "KittenNode.h" -static const NSInteger kLitterSize = 20; // intial number of kitten cells in ASTableView -static const NSInteger kLitterBatchSize = 10; // number of kitten cells to add to ASTableView -static const NSInteger kMaxLitterSize = 100; // max number of kitten cells allowed in ASTableView +static const NSInteger kLitterSize = 20; // intial number of kitten cells in ASTableNode +static const NSInteger kLitterBatchSize = 10; // number of kitten cells to add to ASTableNode +static const NSInteger kMaxLitterSize = 100; // max number of kitten cells allowed in ASTableNode -@interface ViewController () +@interface ViewController () { - ASTableView *_tableView; + ASTableNode *_tableNode; // array of boxed CGSizes corresponding to placekitten.com kittens NSMutableArray *_kittenDataSource; @@ -47,32 +47,40 @@ static const NSInteger kMaxLitterSize = 100; // max number of kitten cell @implementation ViewController -#pragma mark - -#pragma mark UIViewController. +#pragma mark - Lifecycle - (instancetype)init { - if (!(self = [super init])) - return nil; + _tableNode = [[ASTableNode alloc] initWithStyle:UITableViewStylePlain]; + _tableNode.dataSource = self; + _tableNode.delegate = self; - _tableView = [[ASTableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain]; - _tableView.separatorStyle = UITableViewCellSeparatorStyleNone; // KittenNode has its own separator - _tableView.asyncDataSource = self; - _tableView.asyncDelegate = self; + if (!(self = [super initWithNode:_tableNode])) + return nil; + + _tableNode.view.separatorStyle = UITableViewCellSeparatorStyleNone; // KittenNode has its own separator // populate our "data source" with some random kittens _kittenDataSource = [self createLitterWithSize:kLitterSize]; - _blurbNodeIndexPath = [NSIndexPath indexPathForItem:0 inSection:0]; self.title = @"Kittens"; self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemEdit target:self action:@selector(toggleEditingMode)]; - + return self; } +- (void)viewDidLoad +{ + [super viewDidLoad]; + + [self.node addSubnode:_tableNode]; +} + +#pragma mark - Data Model + - (NSMutableArray *)createLitterWithSize:(NSInteger)litterSize { NSMutableArray *kittens = [NSMutableArray arrayWithCapacity:litterSize]; @@ -95,36 +103,21 @@ static const NSInteger kMaxLitterSize = 100; // max number of kitten cell _kittenDataSource = kittenDataSource; } -- (void)viewDidLoad -{ - [super viewDidLoad]; - - [self.view addSubview:_tableView]; -} - -- (void)viewWillLayoutSubviews -{ - _tableView.frame = self.view.bounds; -} - - (void)toggleEditingMode { - [_tableView setEditing:!_tableView.editing animated:YES]; + [_tableNode.view setEditing:!_tableNode.view.editing animated:YES]; } -#pragma mark - -#pragma mark ASTableView. +#pragma mark - ASTableNode -- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath +- (NSInteger)tableNode:(ASTableNode *)tableNode numberOfRowsInSection:(NSInteger)section { - [_tableView deselectRowAtIndexPath:indexPath animated:YES]; - // Assume only kitten nodes are selectable (see -tableView:shouldHighlightRowAtIndexPath:). - KittenNode *node = (KittenNode *)[_tableView nodeForRowAtIndexPath:indexPath]; - [node toggleImageEnlargement]; + // blurb node + kLitterSize kitties + return 1 + _kittenDataSource.count; } -- (ASCellNode *)tableView:(ASTableView *)tableView nodeForRowAtIndexPath:(NSIndexPath *)indexPath +- (ASCellNode *)tableNode:(ASTableNode *)tableNode nodeForRowAtIndexPath:(NSIndexPath *)indexPath { // special-case the first row if ([_blurbNodeIndexPath compare:indexPath] == NSOrderedSame) { @@ -137,34 +130,23 @@ static const NSInteger kMaxLitterSize = 100; // max number of kitten cell return node; } -- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section +- (void)tableNode:(ASTableNode *)tableNode didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - // blurb node + kLitterSize kitties - return 1 + _kittenDataSource.count; + [_tableNode deselectRowAtIndexPath:indexPath animated:YES]; + + // Assume only kitten nodes are selectable (see -tableNode:shouldHighlightRowAtIndexPath:). + KittenNode *node = (KittenNode *)[_tableNode nodeForRowAtIndexPath:indexPath]; + + [node toggleImageEnlargement]; } -- (BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath +- (BOOL)tableNode:(ASTableNode *)tableNode shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath { // Enable selection for kitten nodes return [_blurbNodeIndexPath compare:indexPath] != NSOrderedSame; } -- (void)tableViewLockDataSource:(ASTableView *)tableView -{ - self.dataSourceLocked = YES; -} - -- (void)tableViewUnlockDataSource:(ASTableView *)tableView -{ - self.dataSourceLocked = NO; -} - -- (BOOL)shouldBatchFetchForTableView:(UITableView *)tableView -{ - return _kittenDataSource.count < kMaxLitterSize; -} - -- (void)tableView:(UITableView *)tableView willBeginBatchFetchWithContext:(ASBatchContext *)context +- (void)tableNode:(ASTableNode *)tableNode willBeginBatchFetchWithContext:(nonnull ASBatchContext *)context { dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ // populate a new array of random-sized kittens @@ -181,24 +163,30 @@ static const NSInteger kMaxLitterSize = 100; // max number of kitten cell // add new kittens to the data source & notify table of new indexpaths [_kittenDataSource addObjectsFromArray:moarKittens]; - [tableView insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationFade]; + [tableNode insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationFade]; [context completeBatchFetching:YES]; }); } +- (BOOL)shouldBatchFetchForTableNode:(ASTableNode *)tableNode +{ + return _kittenDataSource.count < kMaxLitterSize; +} + - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { // Enable editing for Kitten nodes return [_blurbNodeIndexPath compare:indexPath] != NSOrderedSame; } -- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath +- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle + forRowAtIndexPath:(NSIndexPath *)indexPath { if (editingStyle == UITableViewCellEditingStyleDelete) { // Assume only kitten nodes are editable (see -tableView:canEditRowAtIndexPath:). [_kittenDataSource removeObjectAtIndex:indexPath.row - 1]; - [_tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; + [_tableNode deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; } } diff --git a/examples/SocialAppLayout/Sample/ViewController.h b/examples/SocialAppLayout/Sample/ViewController.h index 40359e2f0e..bfb359c6b5 100644 --- a/examples/SocialAppLayout/Sample/ViewController.h +++ b/examples/SocialAppLayout/Sample/ViewController.h @@ -15,7 +15,7 @@ // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -#import +#import -@interface ViewController : UIViewController +@interface ViewController : ASViewController @end diff --git a/examples/SocialAppLayout/Sample/ViewController.m b/examples/SocialAppLayout/Sample/ViewController.m index 492861c01b..71458a1ae8 100644 --- a/examples/SocialAppLayout/Sample/ViewController.m +++ b/examples/SocialAppLayout/Sample/ViewController.m @@ -24,45 +24,47 @@ #include -@interface ViewController () +@interface ViewController () -@property (nonatomic, strong) ASTableView *tableView; +@property (nonatomic, strong) ASTableNode *tableNode; @property (nonatomic, strong) NSMutableArray *socialAppDataSource; @end +#pragma mark - Lifecycle @implementation ViewController - (instancetype)init { - self = [super init]; + _tableNode = [[ASTableNode alloc] initWithStyle:UITableViewStylePlain]; + + self = [super initWithNode:_tableNode]; + if (self) { + + _tableNode.delegate = self; + _tableNode.dataSource = self; + _tableNode.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + self.title = @"Timeline"; + [self createSocialAppDataSource]; } + return self; } - -- (void)dealloc -{ - _tableView.asyncDataSource = nil; - _tableView.asyncDelegate = nil; -} - - (void)viewDidLoad { [super viewDidLoad]; - - self.tableView = [[ASTableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain]; - self.tableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; - self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone; // SocialAppNode has its own separator - self.tableView.asyncDataSource = self; - self.tableView.asyncDelegate = self; - [self.view addSubview:self.tableView]; + + // SocialAppNode has its own separator + self.tableNode.view.separatorStyle = UITableViewCellSeparatorStyleNone; } +#pragma mark - Data Model + - (void)createSocialAppDataSource { _socialAppDataSource = [[NSMutableArray alloc] init]; @@ -116,9 +118,9 @@ [_socialAppDataSource addObject:newPost]; } -#pragma mark - ASTableView +#pragma mark - ASTableNode -- (ASCellNodeBlock)tableView:(ASTableView *)tableView nodeBlockForRowAtIndexPath:(nonnull NSIndexPath *)indexPath +- (ASCellNodeBlock)tableNode:(ASTableNode *)tableNode nodeBlockForRowAtIndexPath:(NSIndexPath *)indexPath { Post *post = self.socialAppDataSource[indexPath.row]; return ^{ @@ -126,14 +128,14 @@ }; } -- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section +- (NSInteger)tableNode:(ASTableNode *)tableNode numberOfRowsInSection:(NSInteger)section { return self.socialAppDataSource.count; } -- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath +- (void)tableNode:(ASTableNode *)tableNode didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - PostNode *postNode = (PostNode *)[_tableView nodeForRowAtIndexPath:indexPath]; + PostNode *postNode = (PostNode *)[_tableNode nodeForRowAtIndexPath:indexPath]; Post *post = self.socialAppDataSource[indexPath.row]; BOOL shouldRasterize = postNode.shouldRasterizeDescendants; @@ -142,7 +144,7 @@ NSLog(@"%@ rasterization for %@'s post: %@", shouldRasterize ? @"Enabling" : @"Disabling", post.name, postNode); - [tableView deselectRowAtIndexPath:indexPath animated:YES]; + [tableNode deselectRowAtIndexPath:indexPath animated:YES]; } @end diff --git a/examples/Swift/Sample/ViewController.swift b/examples/Swift/Sample/ViewController.swift index 0982081c0a..66ed35391b 100644 --- a/examples/Swift/Sample/ViewController.swift +++ b/examples/Swift/Sample/ViewController.swift @@ -47,12 +47,12 @@ final class ViewController: ASViewController, ASTableDataSource, ASTableDelegate fatalError("storyboards are incompatible with truth and beauty") } - // MARK: ASTableView data source and delegate. + // MARK: ASTableNode data source and delegate. - func tableView(tableView: ASTableView, nodeForRowAtIndexPath indexPath: NSIndexPath) -> ASCellNode { + func tableNode(tableNode: ASTableNode, nodeForRowAtIndexPath indexPath: NSIndexPath) -> ASCellNode { // Should read the row count directly from table view but // https://github.com/facebook/AsyncDisplayKit/issues/1159 - let rowCount = self.tableView(tableView, numberOfRowsInSection: 0) + let rowCount = self.tableNode(tableNode, numberOfRowsInSection: 0) if state.fetchingMore && indexPath.row == rowCount - 1 { return TailLoadingCellNode() @@ -64,11 +64,11 @@ final class ViewController: ASViewController, ASTableDataSource, ASTableDelegate return node } - func numberOfSectionsInTableView(tableView: UITableView) -> Int { + func numberOfSectionsInTableNode(tableNode: ASTableNode) -> Int { return 1 } - func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + func tableNode(tableNode: ASTableNode, numberOfRowsInSection section: Int) -> Int { var count = state.itemCount if state.fetchingMore { count += 1 @@ -76,7 +76,7 @@ final class ViewController: ASViewController, ASTableDataSource, ASTableDelegate return count } - func tableView(tableView: ASTableView, willBeginBatchFetchWithContext context: ASBatchContext) { + func tableNode(tableNode: ASTableNode, willBeginBatchFetchWithContext context: ASBatchContext) { /// This call will come in on a background thread. Switch to main /// to add our spinner, then fire off our fetch. dispatch_async(dispatch_get_main_queue()) { @@ -95,33 +95,33 @@ final class ViewController: ASViewController, ASTableDataSource, ASTableDelegate } private func renderDiff(oldState: State) { - let tableView = tableNode.view - tableView.beginUpdates() - - // Add or remove items - let rowCountChange = state.itemCount - oldState.itemCount - if rowCountChange > 0 { - let indexPaths = (oldState.itemCount.. 0 { + let indexPaths = (oldState.itemCount.. +@interface GradientTableNode : ASCellNode - (instancetype)initWithElementSize:(CGSize)size; diff --git a/examples/VerticalWithinHorizontalScrolling/Sample/GradientTableNode.mm b/examples/VerticalWithinHorizontalScrolling/Sample/GradientTableNode.mm index 907fa16a4e..8e6c884f11 100644 --- a/examples/VerticalWithinHorizontalScrolling/Sample/GradientTableNode.mm +++ b/examples/VerticalWithinHorizontalScrolling/Sample/GradientTableNode.mm @@ -24,7 +24,8 @@ #import #import -@interface GradientTableNode () + +@interface GradientTableNode () { ASTableNode *_tableNode; CGSize _elementSize; @@ -43,40 +44,37 @@ _elementSize = size; _tableNode = [[ASTableNode alloc] initWithStyle:UITableViewStylePlain]; + _tableNode.delegate = self; + _tableNode.dataSource = self; + + ASRangeTuningParameters rangeTuningParameters; + rangeTuningParameters.leadingBufferScreenfuls = 1.0; + rangeTuningParameters.trailingBufferScreenfuls = 0.5; + [_tableNode setTuningParameters:rangeTuningParameters forRangeType:ASLayoutRangeTypeDisplay]; + [self addSubnode:_tableNode]; return self; } -- (void)didLoad -{ - [super didLoad]; - _tableNode.view.asyncDelegate = self; - _tableNode.view.asyncDataSource = self; - - ASRangeTuningParameters rangeTuningParameters; - rangeTuningParameters.leadingBufferScreenfuls = 1.0; - rangeTuningParameters.trailingBufferScreenfuls = 0.5; - [_tableNode.view setTuningParameters:rangeTuningParameters forRangeType:ASLayoutRangeTypeDisplay]; -} - -- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section +- (NSInteger)tableNode:(ASTableNode *)tableNode numberOfRowsInSection:(NSInteger)section { return 100; } -- (ASCellNode *)tableView:(ASTableView *)tableView nodeForRowAtIndexPath:(NSIndexPath *)indexPath +- (ASCellNode *)tableNode:(ASTableNode *)tableNode nodeForRowAtIndexPath:(NSIndexPath *)indexPath { RandomCoreGraphicsNode *elementNode = [[RandomCoreGraphicsNode alloc] init]; elementNode.style.preferredSize = _elementSize; elementNode.indexPath = [NSIndexPath indexPathForRow:indexPath.row inSection:_pageNumber]; + return elementNode; } -- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath +- (void)tableNode:(ASTableNode *)tableNode didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - [tableView deselectRowAtIndexPath:indexPath animated:NO]; - [_tableNode.view reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone]; + [tableNode deselectRowAtIndexPath:indexPath animated:NO]; + [_tableNode reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone]; } - (void)layout From 2a1f7815cc61872d6db820c1be425b169f11bd86 Mon Sep 17 00:00:00 2001 From: Michael Schneider Date: Mon, 24 Oct 2016 19:02:03 -0700 Subject: [PATCH 40/59] Set sublayout to CGPointZero in ASWrapperLayoutSpec (#2476) --- AsyncDisplayKit/Layout/ASLayoutSpec.mm | 1 + 1 file changed, 1 insertion(+) diff --git a/AsyncDisplayKit/Layout/ASLayoutSpec.mm b/AsyncDisplayKit/Layout/ASLayoutSpec.mm index b645b3c53b..72fe214755 100644 --- a/AsyncDisplayKit/Layout/ASLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASLayoutSpec.mm @@ -337,6 +337,7 @@ ASLayoutElementStyleForwarding CGSize size = constrainedSize.min; for (id child in children) { ASLayout *sublayout = [child layoutThatFits:constrainedSize parentSize:constrainedSize.max]; + sublayout.position = CGPointZero; size.width = MAX(size.width, sublayout.size.width); size.height = MAX(size.height, sublayout.size.height); From 12534ee6fbd09e999f8c6cf5525cd363e329abf8 Mon Sep 17 00:00:00 2001 From: Adlai Holler Date: Mon, 24 Oct 2016 20:11:47 -0700 Subject: [PATCH 41/59] Handle nil in selectItem/RowAtIndexPath: (#2477) --- AsyncDisplayKit/ASCollectionView.mm | 5 +++++ AsyncDisplayKit/ASTableView.mm | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/AsyncDisplayKit/ASCollectionView.mm b/AsyncDisplayKit/ASCollectionView.mm index 27079d1441..27828e29cc 100644 --- a/AsyncDisplayKit/ASCollectionView.mm +++ b/AsyncDisplayKit/ASCollectionView.mm @@ -612,6 +612,11 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell"; - (void)selectItemAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated scrollPosition:(UICollectionViewScrollPosition)scrollPosition { ASDisplayNodeAssertMainThread(); + // If they passed nil, just forward it and be done. + if (indexPath == nil) { + [super selectItemAtIndexPath:indexPath animated:animated scrollPosition:scrollPosition]; + return; + } NSIndexPath *viewIndexPath = [self convertIndexPathFromCollectionNode:indexPath waitingIfNeeded:YES]; if (viewIndexPath != nil) { diff --git a/AsyncDisplayKit/ASTableView.mm b/AsyncDisplayKit/ASTableView.mm index 04f3a5e494..fd879df740 100644 --- a/AsyncDisplayKit/ASTableView.mm +++ b/AsyncDisplayKit/ASTableView.mm @@ -555,6 +555,11 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell"; - (void)selectRowAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated scrollPosition:(UITableViewScrollPosition)scrollPosition { ASDisplayNodeAssertMainThread(); + // If they passed nil, just forward it and be done. + if (indexPath == nil) { + [super selectRowAtIndexPath:indexPath animated:animated scrollPosition:scrollPosition]; + return; + } indexPath = [self convertIndexPathFromTableNode:indexPath waitingIfNeeded:YES]; if (indexPath != nil) { From 6d5bd6e969ba8c426bf0abe3d83597d739148afd Mon Sep 17 00:00:00 2001 From: Michael Schneider Date: Wed, 26 Oct 2016 11:26:57 -0700 Subject: [PATCH 42/59] Cleanup calculateLayoutThatFits: (#2480) --- AsyncDisplayKit/ASDisplayNode+Beta.h | 5 - AsyncDisplayKit/ASDisplayNode+Subclasses.h | 25 ++- AsyncDisplayKit/ASDisplayNode.mm | 172 ++++++++++-------- AsyncDisplayKit/Details/ASEnvironment.h | 5 +- .../Layout/ASAbsoluteLayoutSpec.mm | 10 - .../Layout/ASLayoutSpec+Subclasses.mm | 4 - AsyncDisplayKit/Layout/ASLayoutSpec.mm | 31 ---- AsyncDisplayKit/Layout/ASStackLayoutSpec.mm | 9 - examples/ASDKgram/Sample/CommentsNode.m | 3 +- examples/ASDKgram/Sample/PhotoCellNode.m | 26 ++- 10 files changed, 123 insertions(+), 167 deletions(-) diff --git a/AsyncDisplayKit/ASDisplayNode+Beta.h b/AsyncDisplayKit/ASDisplayNode+Beta.h index 40ff9e10e5..e68d8827ee 100644 --- a/AsyncDisplayKit/ASDisplayNode+Beta.h +++ b/AsyncDisplayKit/ASDisplayNode+Beta.h @@ -63,9 +63,6 @@ typedef struct { + (BOOL)suppressesInvalidCollectionUpdateExceptions AS_WARN_UNUSED_RESULT; + (void)setSuppressesInvalidCollectionUpdateExceptions:(BOOL)suppresses; -/** @name Layout */ - - /** * @abstract Recursively ensures node and all subnodes are displayed. * @see Full documentation in ASDisplayNode+FrameworkPrivate.h @@ -97,8 +94,6 @@ typedef struct { */ @property (nonatomic, assign, readonly) ASDisplayNodePerformanceMeasurements performanceMeasurements; -/** @name Layout Transitioning */ - /** * @abstract Currently used by ASNetworkImageNode and ASMultiplexImageNode to allow their placeholders to stay if they are loading an image from the network. * Otherwise, a display pass is scheduled and completes, but does not actually draw anything - and ASDisplayNode considers the element finished. diff --git a/AsyncDisplayKit/ASDisplayNode+Subclasses.h b/AsyncDisplayKit/ASDisplayNode+Subclasses.h index 4b6a7be8cd..d82353e69c 100644 --- a/AsyncDisplayKit/ASDisplayNode+Subclasses.h +++ b/AsyncDisplayKit/ASDisplayNode+Subclasses.h @@ -41,6 +41,7 @@ NS_ASSUME_NONNULL_BEGIN @interface ASDisplayNode (Subclassing) +#pragma mark - Properties /** @name Properties */ /** @@ -64,9 +65,9 @@ NS_ASSUME_NONNULL_BEGIN */ @property (nullable, nonatomic, readonly, assign) ASLayout *calculatedLayout; +#pragma mark - View Lifecycle /** @name View Lifecycle */ - /** * @abstract Called on the main thread immediately after self.view is created. * @@ -75,9 +76,9 @@ NS_ASSUME_NONNULL_BEGIN - (void)didLoad ASDISPLAYNODE_REQUIRES_SUPER; +#pragma mark - Layout /** @name Layout */ - /** * @abstract Called on the main thread by the view's -layoutSubviews. * @@ -101,6 +102,8 @@ NS_ASSUME_NONNULL_BEGIN */ - (void)calculatedLayoutDidChange ASDISPLAYNODE_REQUIRES_SUPER; + +#pragma mark - Layout calculation /** @name Layout calculation */ /** @@ -159,9 +162,9 @@ NS_ASSUME_NONNULL_BEGIN * * @note This method should not be called directly outside of ASDisplayNode; use -measure: or -calculatedLayout instead. * - * @warning Subclasses that implement -layoutSpecThatFits: must not also use .layoutSpecBlock. Doing so will trigger - * an exception. A future version of the framework may support using both, calling them serially, with the - * .layoutSpecBlock superseding any values set by the method override. + * @warning Subclasses that implement -layoutSpecThatFits: must not use .layoutSpecBlock. Doing so will trigger an + * exception. A future version of the framework may support using both, calling them serially, with the .layoutSpecBlock + * superseding any values set by the method override. */ - (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize; @@ -174,9 +177,9 @@ NS_ASSUME_NONNULL_BEGIN - (void)invalidateCalculatedLayout; +#pragma mark - Drawing /** @name Drawing */ - /** * @summary Delegate method to draw layer contents into a CGBitmapContext. The current UIGraphics context will be set * to an appropriate context. @@ -407,9 +410,9 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, assign, readonly) CGFloat contentsScaleForDisplay; +#pragma mark - Touch handling /** @name Touch handling */ - /** * @abstract Tells the node when touches began in its view. * @@ -443,9 +446,9 @@ NS_ASSUME_NONNULL_BEGIN - (void)touchesCancelled:(nullable NSSet *)touches withEvent:(nullable UIEvent *)event ASDISPLAYNODE_REQUIRES_SUPER; +#pragma mark - Managing Gesture Recognizers /** @name Managing Gesture Recognizers */ - /** * @abstract Asks the node if a gesture recognizer should continue tracking touches. * @@ -454,8 +457,9 @@ NS_ASSUME_NONNULL_BEGIN - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer; -/** @name Hit Testing */ +#pragma mark - Hit Testing +/** @name Hit Testing */ /** * @abstract Returns the view that contains the point. @@ -472,6 +476,8 @@ NS_ASSUME_NONNULL_BEGIN */ - (nullable UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event; + +#pragma mark - Placeholders /** @name Placeholders */ /** @@ -492,6 +498,7 @@ NS_ASSUME_NONNULL_BEGIN - (nullable UIImage *)placeholderImage; +#pragma mark - Description /** @name Description */ /** diff --git a/AsyncDisplayKit/ASDisplayNode.mm b/AsyncDisplayKit/ASDisplayNode.mm index edb1967acf..7b18bc5fd5 100644 --- a/AsyncDisplayKit/ASDisplayNode.mm +++ b/AsyncDisplayKit/ASDisplayNode.mm @@ -186,10 +186,10 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c) // At most a layoutSpecBlock or one of the three layout methods is overridden #define __ASDisplayNodeCheckForLayoutMethodOverrides \ ASDisplayNodeAssert(_layoutSpecBlock != NULL || \ - (ASDisplayNodeSubclassOverridesSelector(self.class, @selector(calculateSizeThatFits:)) ? 1 : 0) \ + ((ASDisplayNodeSubclassOverridesSelector(self.class, @selector(calculateSizeThatFits:)) ? 1 : 0) \ + (ASDisplayNodeSubclassOverridesSelector(self.class, @selector(layoutSpecThatFits:)) ? 1 : 0) \ - + (ASDisplayNodeSubclassOverridesSelector(self.class, @selector(calculateLayoutThatFits:)) ? 1 : 0) <= 1, \ - @"Subclass %@ must at least provide a layoutSpecBlock or override at most one of the three layout methods: calculateLayoutThatFits, layoutSpecThatFits or calculateSizeThatFits", NSStringFromClass(self.class)) + + (ASDisplayNodeSubclassOverridesSelector(self.class, @selector(calculateLayoutThatFits:)) ? 1 : 0)) <= 1, \ + @"Subclass %@ must at least provide a layoutSpecBlock or override at most one of the three layout methods: calculateLayoutThatFits:, layoutSpecThatFits:, or calculateSizeThatFits:", NSStringFromClass(self.class)) + (void)initialize { @@ -199,14 +199,14 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c) // Subclasses should never override these. Use unused to prevent warnings __unused NSString *classString = NSStringFromClass(self); - ASDisplayNodeAssert(!ASDisplayNodeSubclassOverridesSelector(self, @selector(calculatedSize)), @"Subclass %@ must not override calculatedSize method", classString); - ASDisplayNodeAssert(!ASDisplayNodeSubclassOverridesSelector(self, @selector(calculatedLayout)), @"Subclass %@ must not override calculatedLayout method", classString); + ASDisplayNodeAssert(!ASDisplayNodeSubclassOverridesSelector(self, @selector(calculatedSize)), @"Subclass %@ must not override calculatedSize method.", classString); + ASDisplayNodeAssert(!ASDisplayNodeSubclassOverridesSelector(self, @selector(calculatedLayout)), @"Subclass %@ must not override calculatedLayout method.", classString); ASDisplayNodeAssert(!ASDisplayNodeSubclassOverridesSelector(self, @selector(measure:)), @"Subclass %@ must not override measure: method", classString); ASDisplayNodeAssert(!ASDisplayNodeSubclassOverridesSelector(self, @selector(measureWithSizeRange:)), @"Subclass %@ must not override measureWithSizeRange: method. Instead overwrite calculateLayoutThatFits:", classString); - ASDisplayNodeAssert(!ASDisplayNodeSubclassOverridesSelector(self, @selector(layoutThatFits:)), @"Subclass %@ must not override layoutThatFits: method", classString); - ASDisplayNodeAssert(!ASDisplayNodeSubclassOverridesSelector(self, @selector(layoutThatFits:parentSize:)), @"Subclass %@ must not override layoutThatFits:parentSize method", classString); - ASDisplayNodeAssert(!ASDisplayNodeSubclassOverridesSelector(self, @selector(recursivelyClearContents)), @"Subclass %@ must not override recursivelyClearContents method", classString); - ASDisplayNodeAssert(!ASDisplayNodeSubclassOverridesSelector(self, @selector(recursivelyClearFetchedData)), @"Subclass %@ must not override recursivelyClearFetchedData method", classString); + ASDisplayNodeAssert(!ASDisplayNodeSubclassOverridesSelector(self, @selector(layoutThatFits:)), @"Subclass %@ must not override layoutThatFits: method. Instead overwrite calculateLayoutThatFits:.", classString); + ASDisplayNodeAssert(!ASDisplayNodeSubclassOverridesSelector(self, @selector(layoutThatFits:parentSize:)), @"Subclass %@ must not override layoutThatFits:parentSize method. Instead overwrite calculateLayoutThatFits:.", classString); + ASDisplayNodeAssert(!ASDisplayNodeSubclassOverridesSelector(self, @selector(recursivelyClearContents)), @"Subclass %@ must not override recursivelyClearContents method.", classString); + ASDisplayNodeAssert(!ASDisplayNodeSubclassOverridesSelector(self, @selector(recursivelyClearFetchedData)), @"Subclass %@ must not override recursivelyClearFetchedData method.", classString); } // Below we are pre-calculating values per-class and dynamically adding a method (_staticInitialize) to populate these values @@ -232,18 +232,17 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c) #if DEBUG - // Check if subnodes where modified during layoutSpecThatFits: - if (self == [ASDisplayNode class] || ASSubclassOverridesSelector([ASDisplayNode class], self, @selector(layoutSpecThatFits:))) - { - __block IMP originalLayoutSpecThatFitsIMP = ASReplaceMethodWithBlock(self, @selector(layoutSpecThatFits:), ^(ASDisplayNode *_self, ASSizeRange sizeRange) { + // Check if subnodes where modified during the creation of the layout + if (self == [ASDisplayNode class]) { + __block IMP originalLayoutSpecThatFitsIMP = ASReplaceMethodWithBlock(self, @selector(_layoutElementThatFits:), ^(ASDisplayNode *_self, ASSizeRange sizeRange) { NSArray *oldSubnodes = _self.subnodes; - ASLayoutSpec *layoutSpec = ((ASLayoutSpec *( *)(id, SEL, ASSizeRange))originalLayoutSpecThatFitsIMP)(_self, @selector(layoutSpecThatFits:), sizeRange); + ASLayoutSpec *layoutElement = ((ASLayoutSpec *( *)(id, SEL, ASSizeRange))originalLayoutSpecThatFitsIMP)(_self, @selector(_layoutElementThatFits:), sizeRange); NSArray *subnodes = _self.subnodes; - ASDisplayNodeAssert(oldSubnodes.count == subnodes.count, @"Adding or removing nodes in layoutSpecThatFits: is verboten."); + ASDisplayNodeAssert(oldSubnodes.count == subnodes.count, @"Adding or removing nodes in layoutSpecBlock or layoutSpecThatFits: is not allowed and can cause unexpected behavior."); for (NSInteger i = 0; i < oldSubnodes.count; i++) { - ASDisplayNodeAssert(oldSubnodes[i] == subnodes[i], @"Adding and removing nodes in layoutSpecThatFits: is verboten."); + ASDisplayNodeAssert(oldSubnodes[i] == subnodes[i], @"Adding or removing nodes in layoutSpecBlock or layoutSpecThatFits: is not allowed and can cause unexpected behavior."); } - return layoutSpec; + return layoutElement; }); } #endif @@ -2425,62 +2424,67 @@ void recursivelyTriggerDisplayForLayer(CALayer *layer, BOOL shouldBlock) __ASDisplayNodeCheckForLayoutMethodOverrides; ASDN::MutexLocker l(__instanceLock__); - if ((_methodOverrides & ASDisplayNodeMethodOverrideLayoutSpecThatFits) || _layoutSpecBlock != NULL) { - BOOL measureLayoutSpec = _measurementOptions & ASDisplayNodePerformanceMeasurementOptionLayoutSpec; - if (measureLayoutSpec) { - _layoutSpecNumberOfPasses++; - } - ASLayoutSpec *layoutSpec = ({ - ASDN::SumScopeTimer t(_layoutSpecTotalTime, measureLayoutSpec); - [self layoutSpecThatFits:constrainedSize]; - }); - -#if AS_DEDUPE_LAYOUT_SPEC_TREE - NSSet *duplicateElements = [layoutSpec findDuplicatedElementsInSubtree]; - if (duplicateElements.count > 0) { - ASDisplayNodeFailAssert(@"Node %@ returned a layout spec that contains the same elements in multiple positions. Elements: %@", self, duplicateElements); - // Use an empty layout spec to avoid crash. - layoutSpec = [[ASLayoutSpec alloc] init]; - } -#endif - - ASDisplayNodeAssert(layoutSpec.isMutable, @"Node %@ returned layout spec %@ that has already been used. Layout specs should always be regenerated.", self, layoutSpec); - - layoutSpec.parent = self; // This causes upward propogation of any non-default layoutElement values. - - // manually propagate the trait collection here so that any layoutSpec children of layoutSpec will get a traitCollection - { - ASDN::SumScopeTimer t(_layoutSpecTotalTime, measureLayoutSpec); - ASEnvironmentStatePropagateDown(layoutSpec, self.environmentTraitCollection); - } - - layoutSpec.isMutable = NO; - BOOL measureLayoutComputation = _measurementOptions & ASDisplayNodePerformanceMeasurementOptionLayoutComputation; - if (measureLayoutComputation) { - _layoutComputationNumberOfPasses++; - } - - ASLayout *layout = ({ - ASDN::SumScopeTimer t(_layoutComputationTotalTime, measureLayoutComputation); - [layoutSpec layoutThatFits:constrainedSize]; - }); - - ASDisplayNodeAssertNotNil(layout, @"[ASLayoutSpec measureWithSizeRange:] should never return nil! %@, %@", self, layoutSpec); - - // Make sure layoutElementObject of the root layout is `self`, so that the flattened layout will be structurally correct. - BOOL isFinalLayoutElement = (layout.layoutElement != self); - if (isFinalLayoutElement) { - layout.position = CGPointZero; - layout = [ASLayout layoutWithLayoutElement:self size:layout.size sublayouts:@[layout]]; - } - ASDisplayNodeLogEvent(self, @"computedLayout: %@", layout); - return [layout filteredNodeLayoutTree]; - } else { + // Manual size calculation via calculateSizeThatFits: + if (((_methodOverrides & ASDisplayNodeMethodOverrideLayoutSpecThatFits) || + (_layoutSpecBlock != NULL)) == NO) { CGSize size = [self calculateSizeThatFits:constrainedSize.max]; ASDisplayNodeLogEvent(self, @"calculatedSize: %@", NSStringFromCGSize(size)); return [ASLayout layoutWithLayoutElement:self size:ASSizeRangeClamp(constrainedSize, size) sublayouts:nil]; } + + // Size calcualtion with layout elements + BOOL measureLayoutSpec = _measurementOptions & ASDisplayNodePerformanceMeasurementOptionLayoutSpec; + if (measureLayoutSpec) { + _layoutSpecNumberOfPasses++; + } + + // Get layout element from the node + id layoutElement = [self _layoutElementThatFits:constrainedSize]; + + // Certain properties are necessary to set on an element of type ASLayoutSpec + if (layoutElement.layoutElementType == ASLayoutElementTypeLayoutSpec) { + ASLayoutSpec *layoutSpec = (ASLayoutSpec *)layoutElement; + + NSSet *duplicateElements = [layoutSpec findDuplicatedElementsInSubtree]; + if (duplicateElements.count > 0) { + ASDisplayNodeFailAssert(@"Node %@ returned a layout spec that contains the same elements in multiple positions. Elements: %@", self, duplicateElements); + // Use an empty layout spec to avoid crashes + layoutSpec = [[ASLayoutSpec alloc] init]; + } + + ASDisplayNodeAssert(layoutSpec.isMutable, @"Node %@ returned layout spec %@ that has already been used. Layout specs should always be regenerated.", self, layoutSpec); + layoutSpec.parent = self; + layoutSpec.isMutable = NO; + } + + // Manually propagate the trait collection here so that any layoutSpec children of layoutSpec will get a traitCollection + { + ASDN::SumScopeTimer t(_layoutSpecTotalTime, measureLayoutSpec); + ASEnvironmentStatePropagateDown(layoutElement, [self environmentTraitCollection]); + } + + BOOL measureLayoutComputation = _measurementOptions & ASDisplayNodePerformanceMeasurementOptionLayoutComputation; + if (measureLayoutComputation) { + _layoutComputationNumberOfPasses++; + } + + // Layout element layout creation + ASLayout *layout = ({ + ASDN::SumScopeTimer t(_layoutComputationTotalTime, measureLayoutComputation); + [layoutElement layoutThatFits:constrainedSize]; + }); + ASDisplayNodeAssertNotNil(layout, @"[ASLayoutElement layoutThatFits:] should never return nil! %@, %@", self, layout); + + // Make sure layoutElementObject of the root layout is `self`, so that the flattened layout will be structurally correct. + BOOL isFinalLayoutElement = (layout.layoutElement != self); + if (isFinalLayoutElement) { + layout.position = CGPointZero; + layout = [ASLayout layoutWithLayoutElement:self size:layout.size sublayouts:@[layout]]; + } + ASDisplayNodeLogEvent(self, @"computedLayout: %@", layout); + + return [layout filteredNodeLayoutTree]; } - (CGSize)calculateSizeThatFits:(CGSize)constrainedSize @@ -2490,15 +2494,28 @@ void recursivelyTriggerDisplayForLayer(CALayer *layer, BOOL shouldBlock) return CGSizeZero; } +- (id)_layoutElementThatFits:(ASSizeRange)constrainedSize +{ + __ASDisplayNodeCheckForLayoutMethodOverrides; + + BOOL measureLayoutSpec = _measurementOptions & ASDisplayNodePerformanceMeasurementOptionLayoutSpec; + if (_layoutSpecBlock != NULL) { + return ({ + ASDN::MutexLocker l(__instanceLock__); + ASDN::SumScopeTimer t(_layoutSpecTotalTime, measureLayoutSpec); + _layoutSpecBlock(self, constrainedSize); + }); + } else { + return ({ + ASDN::SumScopeTimer t(_layoutSpecTotalTime, measureLayoutSpec); + [self layoutSpecThatFits:constrainedSize]; + }); + } +} + - (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize { __ASDisplayNodeCheckForLayoutMethodOverrides; - - ASDN::MutexLocker l(__instanceLock__); - - if (_layoutSpecBlock != NULL) { - return _layoutSpecBlock(self, constrainedSize); - } ASDisplayNodeAssert(NO, @"-[ASDisplayNode layoutSpecThatFits:] should never return an empty value. One way this is caused is by calling -[super layoutSpecThatFits:] which is not currently supported."); return [[ASLayoutSpec alloc] init]; @@ -2506,7 +2523,7 @@ void recursivelyTriggerDisplayForLayer(CALayer *layer, BOOL shouldBlock) - (void)setLayoutSpecBlock:(ASLayoutSpecBlock)layoutSpecBlock { - // For now there should never be a overwrite of layoutSpecThatFits: and a layoutSpecThatFitsBlock: be provided + // For now there should never be an overwrite of layoutSpecThatFits: / layoutElementThatFits: and a layoutSpecBlock ASDisplayNodeAssert(!(_methodOverrides & ASDisplayNodeMethodOverrideLayoutSpecThatFits), @"Overwriting layoutSpecThatFits: and providing a layoutSpecBlock block is currently not supported"); ASDN::MutexLocker l(__instanceLock__); @@ -3421,11 +3438,6 @@ static const char *ASDisplayNodeDrawingPriorityKey = "ASDrawingPriority"; return self.subnodes; } -- (BOOL)supportsUpwardPropagation -{ - return ASEnvironmentStatePropagationEnabled(); -} - - (BOOL)supportsTraitsCollectionPropagation { return ASEnvironmentStateTraitCollectionPropagationEnabled(); diff --git a/AsyncDisplayKit/Details/ASEnvironment.h b/AsyncDisplayKit/Details/ASEnvironment.h index 4fcb27f356..e8f2bf6159 100644 --- a/AsyncDisplayKit/Details/ASEnvironment.h +++ b/AsyncDisplayKit/Details/ASEnvironment.h @@ -110,8 +110,9 @@ ASDISPLAYNODE_EXTERN_C_END /// Returns all children of an object which class conforms to the ASEnvironment protocol - (nullable NSArray> *)children; -/// Classes should implement this method and return YES / NO dependent if upward propagation is enabled or not -- (BOOL)supportsUpwardPropagation; +/// Classes should implement this method and return YES / NO dependent if upward propagation is enabled or not +// Currently this is disabled as propagation of any attributions besides trait collections is not supported at the moment +// - (BOOL)supportsUpwardPropagation; /// Classes should implement this method and return YES / NO dependent if downware propagation is enabled or not - (BOOL)supportsTraitsCollectionPropagation; diff --git a/AsyncDisplayKit/Layout/ASAbsoluteLayoutSpec.mm b/AsyncDisplayKit/Layout/ASAbsoluteLayoutSpec.mm index 38be927ef6..c4506ad72d 100644 --- a/AsyncDisplayKit/Layout/ASAbsoluteLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASAbsoluteLayoutSpec.mm @@ -100,16 +100,6 @@ @end -#pragma mark - ASEnvironment - -@implementation ASAbsoluteLayoutSpec (ASEnvironment) - -- (BOOL)supportsUpwardPropagation -{ - return NO; -} - -@end #pragma mark - Debugging diff --git a/AsyncDisplayKit/Layout/ASLayoutSpec+Subclasses.mm b/AsyncDisplayKit/Layout/ASLayoutSpec+Subclasses.mm index 517f25aac9..ed186d4a0c 100644 --- a/AsyncDisplayKit/Layout/ASLayoutSpec+Subclasses.mm +++ b/AsyncDisplayKit/Layout/ASLayoutSpec+Subclasses.mm @@ -88,10 +88,6 @@ // Replace object at the given index with the layoutElement _childrenArray[index] = layoutElement; - - // TODO: Should we propagate up the layoutElement at it could happen that multiple children will propagated up their - // layout options and one child will overwrite values from another child - // [self propagateUpLayoutElement:finalLayoutElement]; } - (id)childAtIndex:(NSUInteger)index diff --git a/AsyncDisplayKit/Layout/ASLayoutSpec.mm b/AsyncDisplayKit/Layout/ASLayoutSpec.mm index 72fe214755..ef9643e44e 100644 --- a/AsyncDisplayKit/Layout/ASLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASLayoutSpec.mm @@ -105,19 +105,6 @@ return [ASLayout layoutWithLayoutElement:self size:constrainedSize.min]; } - -#pragma mark - Parent - -- (void)setParent:(id)parent -{ - // FIXME: Locking should be evaluated here. _parent is not widely used yet, though. - _parent = parent; - - if ([parent supportsUpwardPropagation]) { - ASEnvironmentStatePropagateUp(parent, self.environmentState.layoutOptionsState); - } -} - #pragma mark - Child - (void)setChild:(id)child @@ -129,7 +116,6 @@ id finalLayoutElement = [self layoutElementToAddFromLayoutElement:child]; if (finalLayoutElement) { _childrenArray[0] = finalLayoutElement; - [self propagateUpLayoutElement:finalLayoutElement]; } } else { if (_childrenArray.count) { @@ -185,28 +171,11 @@ _environmentState = environmentState; } -// Subclasses can override this method to return NO, because upward propagation is not enabled if a layout -// specification has more than one child. Currently ASStackLayoutSpec and ASAbsoluteLayoutSpec are currently -// the specifications that are known to have more than one. -- (BOOL)supportsUpwardPropagation -{ - return ASEnvironmentStatePropagationEnabled(); -} - - (BOOL)supportsTraitsCollectionPropagation { return ASEnvironmentStateTraitCollectionPropagationEnabled(); } -- (void)propagateUpLayoutElement:(id)layoutElement -{ - if ([layoutElement isKindOfClass:[ASLayoutSpec class]]) { - [(ASLayoutSpec *)layoutElement setParent:self]; // This will trigger upward propogation if needed. - } else if ([self supportsUpwardPropagation]) { - ASEnvironmentStatePropagateUp(self, layoutElement.environmentState.layoutOptionsState); // Probably an ASDisplayNode - } -} - - (ASEnvironmentTraitCollection)environmentTraitCollection { return _environmentState.environmentTraitCollection; diff --git a/AsyncDisplayKit/Layout/ASStackLayoutSpec.mm b/AsyncDisplayKit/Layout/ASStackLayoutSpec.mm index 463327dcf6..2f261b681f 100644 --- a/AsyncDisplayKit/Layout/ASStackLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASStackLayoutSpec.mm @@ -182,15 +182,6 @@ @end -@implementation ASStackLayoutSpec (ASEnvironment) - -- (BOOL)supportsUpwardPropagation -{ - return NO; -} - -@end - @implementation ASStackLayoutSpec (Debugging) #pragma mark - ASLayoutElementAsciiArtProtocol diff --git a/examples/ASDKgram/Sample/CommentsNode.m b/examples/ASDKgram/Sample/CommentsNode.m index 56e270faa5..0d3b936c4e 100644 --- a/examples/ASDKgram/Sample/CommentsNode.m +++ b/examples/ASDKgram/Sample/CommentsNode.m @@ -45,8 +45,7 @@ { ASStackLayoutSpec *verticalStack = [ASStackLayoutSpec verticalStackLayoutSpec]; verticalStack.spacing = INTER_COMMENT_SPACING; - [verticalStack setChildren:_commentNodes]; - + verticalStack.children = [_commentNodes copy]; return verticalStack; } diff --git a/examples/ASDKgram/Sample/PhotoCellNode.m b/examples/ASDKgram/Sample/PhotoCellNode.m index db5f8b55b3..2926b3296e 100644 --- a/examples/ASDKgram/Sample/PhotoCellNode.m +++ b/examples/ASDKgram/Sample/PhotoCellNode.m @@ -116,30 +116,26 @@ _photoLocationLabel.style.flexShrink = 1.0; _userNameLabel.style.flexShrink = 1.0; - ASStackLayoutSpec *headerSubStack = [ASStackLayoutSpec verticalStackLayoutSpec]; + ASStackLayoutSpec *headerSubStack = [ASStackLayoutSpec verticalStackLayoutSpec]; headerSubStack.style.flexShrink = 1.0; - if (_photoLocationLabel.attributedText) { - [headerSubStack setChildren:@[_userNameLabel, _photoLocationLabel]]; - } else { - [headerSubStack setChildren:@[_userNameLabel]]; - } - + headerSubStack.children = _photoLocationLabel.attributedText ? @[_userNameLabel, _photoLocationLabel] + : @[_userNameLabel]; // header stack // constrain avatar image frame size _userAvatarImageView.style.preferredSize = CGSizeMake(USER_IMAGE_HEIGHT, USER_IMAGE_HEIGHT); - _photoTimeIntervalSincePostLabel.style.spacingBefore = HORIZONTAL_BUFFER; // to remove double spaces around spacer + _photoTimeIntervalSincePostLabel.style.spacingBefore = HORIZONTAL_BUFFER; // to remove double spaces around spacer - ASLayoutSpec *spacer = [[ASLayoutSpec alloc] init]; // FIXME: long locations overflow post time - set max size? + ASLayoutSpec *spacer = [[ASLayoutSpec alloc] init]; // FIXME: long locations overflow post time - set max size? spacer.style.flexGrow = 1.0; UIEdgeInsets avatarInsets = UIEdgeInsetsMake(HORIZONTAL_BUFFER, 0, HORIZONTAL_BUFFER, HORIZONTAL_BUFFER); ASInsetLayoutSpec *avatarInset = [ASInsetLayoutSpec insetLayoutSpecWithInsets:avatarInsets child:_userAvatarImageView]; ASStackLayoutSpec *headerStack = [ASStackLayoutSpec horizontalStackLayoutSpec]; - headerStack.alignItems = ASStackLayoutAlignItemsCenter; // center items vertically in horizontal stack - headerStack.justifyContent = ASStackLayoutJustifyContentStart; // justify content to the left side of the header stack - [headerStack setChildren:@[avatarInset, headerSubStack, spacer, _photoTimeIntervalSincePostLabel]]; + headerStack.alignItems = ASStackLayoutAlignItemsCenter; // center items vertically in horizontal stack + headerStack.justifyContent = ASStackLayoutJustifyContentStart; // justify content to the left side of the header stack + headerStack.children = @[avatarInset, headerSubStack, spacer, _photoTimeIntervalSincePostLabel]; // header inset stack UIEdgeInsets insets = UIEdgeInsetsMake(0, HORIZONTAL_BUFFER, 0, HORIZONTAL_BUFFER); @@ -148,7 +144,7 @@ // footer stack ASStackLayoutSpec *footerStack = [ASStackLayoutSpec verticalStackLayoutSpec]; footerStack.spacing = VERTICAL_BUFFER; - [footerStack setChildren:@[_photoLikesLabel, _photoDescriptionLabel, _photoCommentsView]]; + footerStack.children = @[_photoLikesLabel, _photoDescriptionLabel, _photoCommentsView]; // footer inset stack UIEdgeInsets footerInsets = UIEdgeInsetsMake(VERTICAL_BUFFER, HORIZONTAL_BUFFER, VERTICAL_BUFFER, HORIZONTAL_BUFFER); @@ -161,8 +157,8 @@ _photoImageView.style.preferredSize = CGSizeMake(cellWidth, cellWidth); ASStackLayoutSpec *verticalStack = [ASStackLayoutSpec verticalStackLayoutSpec]; - verticalStack.alignItems = ASStackLayoutAlignItemsStretch; // stretch headerStack to fill horizontal space - [verticalStack setChildren:@[headerWithInset, _photoImageView, footerWithInset]]; + verticalStack.alignItems = ASStackLayoutAlignItemsStretch; // stretch headerStack to fill horizontal space + verticalStack.children = @[headerWithInset, _photoImageView, footerWithInset]; return verticalStack; } From ea9d7851806a61e71a299b7a90e1ec0eb27585b4 Mon Sep 17 00:00:00 2001 From: george-gw Date: Wed, 26 Oct 2016 20:38:21 +0200 Subject: [PATCH 43/59] Call reloadData if necessary when accessing specific methods. (#2479) Added test case. --- AsyncDisplayKit/ASCollectionNode.mm | 10 +++++++ AsyncDisplayKit/ASTableNode.mm | 10 +++++++ AsyncDisplayKitTests/ASCollectionViewTests.mm | 28 +++++++++++++++++++ 3 files changed, 48 insertions(+) diff --git a/AsyncDisplayKit/ASCollectionNode.mm b/AsyncDisplayKit/ASCollectionNode.mm index 69f8bc25d6..9c7b226b81 100644 --- a/AsyncDisplayKit/ASCollectionNode.mm +++ b/AsyncDisplayKit/ASCollectionNode.mm @@ -337,13 +337,22 @@ #pragma mark - Querying Data +- (void)reloadDataInitiallyIfNeeded +{ + if (!self.dataController.initialReloadDataHasBeenCalled) { + [self reloadData]; + } +} + - (NSInteger)numberOfItemsInSection:(NSInteger)section { + [self reloadDataInitiallyIfNeeded]; return [self.dataController numberOfRowsInSection:section]; } - (NSInteger)numberOfSections { + [self reloadDataInitiallyIfNeeded]; return [self.dataController numberOfSections]; } @@ -373,6 +382,7 @@ - (ASCellNode *)nodeForItemAtIndexPath:(NSIndexPath *)indexPath { + [self reloadDataInitiallyIfNeeded]; return [self.dataController nodeAtIndexPath:indexPath]; } diff --git a/AsyncDisplayKit/ASTableNode.mm b/AsyncDisplayKit/ASTableNode.mm index f2f2f7e126..c2b8513ff1 100644 --- a/AsyncDisplayKit/ASTableNode.mm +++ b/AsyncDisplayKit/ASTableNode.mm @@ -361,13 +361,22 @@ ASEnvironmentCollectionTableSetEnvironmentState(_environmentStateLock) #pragma mark - Querying Data +- (void)reloadDataInitiallyIfNeeded +{ + if (!self.dataController.initialReloadDataHasBeenCalled) { + [self reloadData]; + } +} + - (NSInteger)numberOfRowsInSection:(NSInteger)section { + [self reloadDataInitiallyIfNeeded]; return [self.dataController numberOfRowsInSection:section]; } - (NSInteger)numberOfSections { + [self reloadDataInitiallyIfNeeded]; return [self.dataController numberOfSections]; } @@ -384,6 +393,7 @@ ASEnvironmentCollectionTableSetEnvironmentState(_environmentStateLock) - (ASCellNode *)nodeForRowAtIndexPath:(NSIndexPath *)indexPath { + [self reloadDataInitiallyIfNeeded]; return [self.dataController nodeAtIndexPath:indexPath]; } diff --git a/AsyncDisplayKitTests/ASCollectionViewTests.mm b/AsyncDisplayKitTests/ASCollectionViewTests.mm index 0bd538cacb..f19d8fa0fb 100644 --- a/AsyncDisplayKitTests/ASCollectionViewTests.mm +++ b/AsyncDisplayKitTests/ASCollectionViewTests.mm @@ -210,6 +210,34 @@ XCTAssertEqualObjects([collectionView supplementaryNodeKindsInDataController:nil], @[UICollectionElementKindSectionHeader]); } +- (void)testReloadIfNeeded +{ + [ASDisplayNode setSuppressesInvalidCollectionUpdateExceptions:NO]; + + __block ASCollectionViewTestController *testController = [[ASCollectionViewTestController alloc] initWithNibName:nil bundle:nil]; + __block ASCollectionViewTestDelegate *del = testController.asyncDelegate; + __block ASCollectionNode *cn = testController.collectionNode; + + void (^reset)() = ^void() { + testController = [[ASCollectionViewTestController alloc] initWithNibName:nil bundle:nil]; + del = testController.asyncDelegate; + cn = testController.collectionNode; + }; + + // Check if the number of sections matches the data source + XCTAssertEqual(cn.numberOfSections, del->_itemCounts.size(), @"Section count doesn't match the data source"); + + // Reset everything and then check if numberOfItemsInSection matches the data source + reset(); + XCTAssertEqual([cn numberOfItemsInSection:0], del->_itemCounts[0], @"Number of items in Section doesn't match the data source"); + + // Reset and check if we can get the node corresponding to a specific indexPath + reset(); + NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:0]; + ASTextCellNodeWithSetSelectedCounter *node = (ASTextCellNodeWithSetSelectedCounter*)[cn nodeForItemAtIndexPath:indexPath]; + XCTAssertTrue([node.text isEqualToString:indexPath.description], @"Node's text should match the initial text it was created with"); +} + - (void)testSelection { ASCollectionViewTestController *testController = [[ASCollectionViewTestController alloc] initWithNibName:nil bundle:nil]; From 5651606684759878434854eba802ee17dcba450a Mon Sep 17 00:00:00 2001 From: Garrett Moon Date: Wed, 26 Oct 2016 11:42:29 -0700 Subject: [PATCH 44/59] [ASCollectionView] layoutInspector can be nil'd at anytime making flags unsafe (#2473) * Call layoutInspector before checking flags. Thanks @adlai! * Don't create layout inspector with nil layout. --- AsyncDisplayKit/ASCollectionView.mm | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/AsyncDisplayKit/ASCollectionView.mm b/AsyncDisplayKit/ASCollectionView.mm index 27828e29cc..adc9bc58ae 100644 --- a/AsyncDisplayKit/ASCollectionView.mm +++ b/AsyncDisplayKit/ASCollectionView.mm @@ -404,8 +404,10 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell"; super.dataSource = (id)_proxyDataSource; + //Cache results of layoutInspector to ensure flags are up to date if getter lazily loads a new one. + id layoutInspector = self.layoutInspector; if (_layoutInspectorFlags.didChangeCollectionViewDataSource) { - [self.layoutInspector didChangeCollectionViewDataSource:asyncDataSource]; + [layoutInspector didChangeCollectionViewDataSource:asyncDataSource]; } } @@ -465,8 +467,10 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell"; super.delegate = (id)_proxyDelegate; + //Cache results of layoutInspector to ensure flags are up to date if getter lazily loads a new one. + id layoutInspector = self.layoutInspector; if (_layoutInspectorFlags.didChangeCollectionViewDelegate) { - [self.layoutInspector didChangeCollectionViewDelegate:asyncDelegate]; + [layoutInspector didChangeCollectionViewDelegate:asyncDelegate]; } } @@ -485,6 +489,11 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell"; { if (_layoutInspector == nil) { UICollectionViewFlowLayout *layout = (UICollectionViewFlowLayout *)self.collectionViewLayout; + if (layout == nil) { + // Layout hasn't been set yet, we're still init'ing + return nil; + } + if ([layout asdk_isFlowLayout]) { // Register the default layout inspector delegate for flow layouts only _defaultLayoutInspector = [[ASCollectionViewFlowLayoutInspector alloc] initWithCollectionView:self flowLayout:layout]; @@ -1118,8 +1127,10 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell"; - (ASScrollDirection)scrollableDirections { + //Cache results of layoutInspector to ensure flags are up to date if getter lazily loads a new one. + id layoutInspector = self.layoutInspector; if (_layoutInspectorFlags.scrollableDirections) { - return [self.layoutInspector scrollableDirections]; + return [layoutInspector scrollableDirections]; } else { ASScrollDirection scrollableDirection = ASScrollDirectionNone; CGFloat totalContentWidth = self.contentSize.width + self.contentInset.left + self.contentInset.right; From d4af95c9f1be997a2186122c470fc147087bab6d Mon Sep 17 00:00:00 2001 From: Michael Schneider Date: Wed, 26 Oct 2016 11:43:14 -0700 Subject: [PATCH 45/59] Add ASLayoutSizeAuto (#2478) --- AsyncDisplayKit/Layout/ASDimension.h | 2 ++ AsyncDisplayKit/Layout/ASDimension.mm | 2 ++ 2 files changed, 4 insertions(+) diff --git a/AsyncDisplayKit/Layout/ASDimension.h b/AsyncDisplayKit/Layout/ASDimension.h index 5fd9a375f6..c8889d9e7f 100644 --- a/AsyncDisplayKit/Layout/ASDimension.h +++ b/AsyncDisplayKit/Layout/ASDimension.h @@ -192,6 +192,8 @@ typedef struct { ASDimension height; } ASLayoutSize; +extern ASLayoutSize const ASLayoutSizeAuto; + /* * Creates an ASLayoutSize with provided min and max dimensions. */ diff --git a/AsyncDisplayKit/Layout/ASDimension.mm b/AsyncDisplayKit/Layout/ASDimension.mm index ff49a3de0b..c2cf83998b 100644 --- a/AsyncDisplayKit/Layout/ASDimension.mm +++ b/AsyncDisplayKit/Layout/ASDimension.mm @@ -72,6 +72,8 @@ NSString *NSStringFromASDimension(ASDimension dimension) #pragma mark - ASLayoutSize +ASLayoutSize const ASLayoutSizeAuto = {ASDimensionAuto, ASDimensionAuto}; + // ** Resolve this relative size relative to a parent size. */ ASDISPLAYNODE_INLINE CGSize ASLayoutSizeResolveSize(ASLayoutSize layoutSize, CGSize parentSize, CGSize autoSize) { From 627d146a5a9be2c5c2b0b317a121da515b235e34 Mon Sep 17 00:00:00 2001 From: Adlai Holler Date: Wed, 26 Oct 2016 12:48:25 -0700 Subject: [PATCH 46/59] Add scrollToItem: Method to Node, Handle Section Index Paths (#2462) * Add scrollToItem: method to node, handle section index paths * Update ASPagerNode.mm to use the node version * Add some docs --- AsyncDisplayKit/ASCollectionNode.h | 11 +++++ AsyncDisplayKit/ASCollectionNode.mm | 14 ++++++ AsyncDisplayKit/ASCollectionView.h | 9 ++++ AsyncDisplayKit/ASCollectionView.mm | 45 +++++++++---------- AsyncDisplayKit/ASPagerNode.m | 2 +- AsyncDisplayKit/ASTableNode.h | 11 +++++ AsyncDisplayKit/ASTableNode.mm | 14 ++++++ AsyncDisplayKit/ASTableView.h | 9 ++++ AsyncDisplayKit/ASTableView.mm | 39 +++++++--------- AsyncDisplayKit/ASTableViewInternal.h | 8 ++++ .../Details/ASCollectionInternal.h | 9 ++++ 11 files changed, 122 insertions(+), 49 deletions(-) diff --git a/AsyncDisplayKit/ASCollectionNode.h b/AsyncDisplayKit/ASCollectionNode.h index 2e0c38cf97..bb3dfae87b 100644 --- a/AsyncDisplayKit/ASCollectionNode.h +++ b/AsyncDisplayKit/ASCollectionNode.h @@ -136,6 +136,17 @@ NS_ASSUME_NONNULL_BEGIN */ - (void)setTuningParameters:(ASRangeTuningParameters)tuningParameters forRangeMode:(ASLayoutRangeMode)rangeMode rangeType:(ASLayoutRangeType)rangeType; +/** + * Scrolls the collection to the given item. + * + * @param indexPath The index path of the item. + * @param scrollPosition Where the item should end up after the scroll. + * @param animated Whether the scroll should be animated or not. + * + * This method must be called on the main thread. + */ +- (void)scrollToItemAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UICollectionViewScrollPosition)scrollPosition animated:(BOOL)animated; + #pragma mark - Editing /** diff --git a/AsyncDisplayKit/ASCollectionNode.mm b/AsyncDisplayKit/ASCollectionNode.mm index 9c7b226b81..a073769b08 100644 --- a/AsyncDisplayKit/ASCollectionNode.mm +++ b/AsyncDisplayKit/ASCollectionNode.mm @@ -335,6 +335,20 @@ [self.view deselectItemAtIndexPath:indexPath animated:animated]; } +- (void)scrollToItemAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UICollectionViewScrollPosition)scrollPosition animated:(BOOL)animated +{ + ASDisplayNodeAssertMainThread(); + ASCollectionView *collectionView = self.view; + + indexPath = [collectionView convertIndexPathFromCollectionNode:indexPath waitingIfNeeded:YES]; + + if (indexPath != nil) { + [collectionView scrollToItemAtIndexPath:indexPath atScrollPosition:scrollPosition animated:animated]; + } else { + NSLog(@"Failed to scroll to item at index path %@ because the item never reached the view.", indexPath); + } +} + #pragma mark - Querying Data - (void)reloadDataInitiallyIfNeeded diff --git a/AsyncDisplayKit/ASCollectionView.h b/AsyncDisplayKit/ASCollectionView.h index 35f1307a1a..33806b4c00 100644 --- a/AsyncDisplayKit/ASCollectionView.h +++ b/AsyncDisplayKit/ASCollectionView.h @@ -205,6 +205,15 @@ NS_ASSUME_NONNULL_BEGIN */ - (void)setTuningParameters:(ASRangeTuningParameters)tuningParameters forRangeMode:(ASLayoutRangeMode)rangeMode rangeType:(ASLayoutRangeType)rangeType ASDISPLAYNODE_DEPRECATED_MSG("Use ASCollectionNode method instead."); +/** + * Scrolls the collection to the given item. + * + * @param indexPath The index path of the item. + * @param scrollPosition Where the row should end up after the scroll. + * @param animated Whether the scroll should be animated or not. + */ +- (void)scrollToItemAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UICollectionViewScrollPosition)scrollPosition animated:(BOOL)animated ASDISPLAYNODE_DEPRECATED_MSG("Use ASCollectionNode method instead."); + /** * Perform a batch of updates asynchronously, optionally disabling all animations in the batch. This method must be called from the main thread. * The asyncDataSource must be updated to reflect the changes before the update block completes. diff --git a/AsyncDisplayKit/ASCollectionView.mm b/AsyncDisplayKit/ASCollectionView.mm index adc9bc58ae..06aab6899b 100644 --- a/AsyncDisplayKit/ASCollectionView.mm +++ b/AsyncDisplayKit/ASCollectionView.mm @@ -555,19 +555,31 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell"; - (NSIndexPath *)convertIndexPathFromCollectionNode:(NSIndexPath *)indexPath waitingIfNeeded:(BOOL)wait { - ASCellNode *node = [_dataController nodeAtIndexPath:indexPath]; - NSIndexPath *viewIndexPath = [self indexPathForNode:node]; - if (viewIndexPath == nil && wait) { - [self waitUntilAllUpdatesAreCommitted]; - viewIndexPath = [self indexPathForNode:node]; + // If this is a section index path, we don't currently have a method + // to do a mapping. + if (indexPath.item == NSNotFound) { + return indexPath; + } else { + ASCellNode *node = [_dataController nodeAtIndexPath:indexPath]; + NSIndexPath *viewIndexPath = [self indexPathForNode:node]; + if (viewIndexPath == nil && wait) { + [self waitUntilAllUpdatesAreCommitted]; + viewIndexPath = [self indexPathForNode:node]; + } + return viewIndexPath; } - return viewIndexPath; } - (NSIndexPath *)convertIndexPathToCollectionNode:(NSIndexPath *)indexPath { - ASCellNode *node = [self nodeForItemAtIndexPath:indexPath]; - return [_dataController indexPathForNode:node]; + // If this is a section index path, we don't currently have a method + // to do a mapping. + if (indexPath.item == NSNotFound) { + return indexPath; + } else { + ASCellNode *node = [self nodeForItemAtIndexPath:indexPath]; + return [_dataController indexPathForNode:node]; + } } - (ASCellNode *)supplementaryNodeForElementKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath @@ -596,23 +608,6 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell"; return visibleNodes; } -/** - * TODO: This method was built when the distinction between data source - * index paths and view index paths was unclear. For compatibility, it - * still expects data source index paths for the time being. - */ -- (void)scrollToItemAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UICollectionViewScrollPosition)scrollPosition animated:(BOOL)animated -{ - ASDisplayNodeAssertMainThread(); - - NSIndexPath *viewIndexPath = [self convertIndexPathFromCollectionNode:indexPath waitingIfNeeded:YES]; - if (viewIndexPath != nil) { - [super scrollToItemAtIndexPath:viewIndexPath atScrollPosition:scrollPosition animated:animated]; - } else { - NSLog(@"Warning: Ignoring request to scroll to item at index path %@ because the item did not reach the collection view.", indexPath); - } -} - /** * TODO: This method was built when the distinction between data source * index paths and view index paths was unclear. For compatibility, it diff --git a/AsyncDisplayKit/ASPagerNode.m b/AsyncDisplayKit/ASPagerNode.m index 0b42f2bc19..15a6ccb975 100644 --- a/AsyncDisplayKit/ASPagerNode.m +++ b/AsyncDisplayKit/ASPagerNode.m @@ -101,7 +101,7 @@ - (void)scrollToPageAtIndex:(NSInteger)index animated:(BOOL)animated { NSIndexPath *indexPath = [NSIndexPath indexPathForItem:index inSection:0]; - [self.view scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionLeft animated:animated]; + [self scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionLeft animated:animated]; } - (ASCellNode *)nodeForPageAtIndex:(NSInteger)index diff --git a/AsyncDisplayKit/ASTableNode.h b/AsyncDisplayKit/ASTableNode.h index 540f644aaf..83ae540cc7 100644 --- a/AsyncDisplayKit/ASTableNode.h +++ b/AsyncDisplayKit/ASTableNode.h @@ -104,6 +104,17 @@ NS_ASSUME_NONNULL_BEGIN */ - (void)setTuningParameters:(ASRangeTuningParameters)tuningParameters forRangeMode:(ASLayoutRangeMode)rangeMode rangeType:(ASLayoutRangeType)rangeType; +/** + * Scrolls the table to the given row. + * + * @param indexPath The index path of the row. + * @param scrollPosition Where the row should end up after the scroll. + * @param animated Whether the scroll should be animated or not. + * + * This method must be called on the main thread. + */ +- (void)scrollToRowAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UITableViewScrollPosition)scrollPosition animated:(BOOL)animated; + /** * Reload everything from scratch, destroying the working range and all cached nodes. * diff --git a/AsyncDisplayKit/ASTableNode.mm b/AsyncDisplayKit/ASTableNode.mm index c2b8513ff1..954a2ae26e 100644 --- a/AsyncDisplayKit/ASTableNode.mm +++ b/AsyncDisplayKit/ASTableNode.mm @@ -359,6 +359,20 @@ ASEnvironmentCollectionTableSetEnvironmentState(_environmentStateLock) [self.view deselectRowAtIndexPath:indexPath animated:animated]; } +- (void)scrollToRowAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UITableViewScrollPosition)scrollPosition animated:(BOOL)animated +{ + ASDisplayNodeAssertMainThread(); + ASTableView *tableView = self.view; + + indexPath = [tableView convertIndexPathFromTableNode:indexPath waitingIfNeeded:YES]; + + if (indexPath != nil) { + [tableView scrollToRowAtIndexPath:indexPath atScrollPosition:scrollPosition animated:animated]; + } else { + NSLog(@"Failed to scroll to row at index path %@ because the row never reached the view.", indexPath); + } +} + #pragma mark - Querying Data - (void)reloadDataInitiallyIfNeeded diff --git a/AsyncDisplayKit/ASTableView.h b/AsyncDisplayKit/ASTableView.h index 301e94378b..2bed257651 100644 --- a/AsyncDisplayKit/ASTableView.h +++ b/AsyncDisplayKit/ASTableView.h @@ -124,6 +124,15 @@ NS_ASSUME_NONNULL_BEGIN */ - (void)setTuningParameters:(ASRangeTuningParameters)tuningParameters forRangeMode:(ASLayoutRangeMode)rangeMode rangeType:(ASLayoutRangeType)rangeType ASDISPLAYNODE_DEPRECATED_MSG("Use ASTableNode method instead."); +/** + * Scrolls the table to the given row. + * + * @param indexPath The index path of the row. + * @param scrollPosition Where the row should end up after the scroll. + * @param animated Whether the scroll should be animated or not. + */ +- (void)scrollToRowAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UITableViewScrollPosition)scrollPosition animated:(BOOL)animated ASDISPLAYNODE_DEPRECATED_MSG("Use ASTableNode method instead."); + /** * Similar to -visibleCells. * diff --git a/AsyncDisplayKit/ASTableView.mm b/AsyncDisplayKit/ASTableView.mm index fd879df740..e51a92cec1 100644 --- a/AsyncDisplayKit/ASTableView.mm +++ b/AsyncDisplayKit/ASTableView.mm @@ -464,14 +464,26 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell"; - (NSIndexPath *)convertIndexPathFromTableNode:(NSIndexPath *)indexPath waitingIfNeeded:(BOOL)wait { - ASCellNode *node = [_dataController nodeAtIndexPath:indexPath]; - return [self indexPathForNode:node waitingIfNeeded:wait]; + // If this is a section index path, we don't currently have a method + // to do a mapping. + if (indexPath.row == NSNotFound) { + return indexPath; + } else { + ASCellNode *node = [_dataController nodeAtIndexPath:indexPath]; + return [self indexPathForNode:node waitingIfNeeded:wait]; + } } - (NSIndexPath *)convertIndexPathToTableNode:(NSIndexPath *)indexPath { - ASCellNode *node = [self nodeForRowAtIndexPath:indexPath]; - return [_dataController indexPathForNode:node]; + // If this is a section index path, we don't currently have a method + // to do a mapping. + if (indexPath.row == NSNotFound) { + return indexPath; + } else { + ASCellNode *node = [self nodeForRowAtIndexPath:indexPath]; + return [_dataController indexPathForNode:node]; + } } - (NSIndexPath *)indexPathForNode:(ASCellNode *)cellNode @@ -528,25 +540,6 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell"; [_dataController waitUntilAllUpdatesAreCommitted]; } -/** - * TODO: This method was built when the distinction between data source - * index paths and view index paths was unclear. For compatibility, it - * still expects data source index paths for the time being. - * When the behavior is changed (to use the view index path directly) - * we should also remove the @c convertIndexPathFromTableNode: method. - */ -- (void)scrollToRowAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UITableViewScrollPosition)scrollPosition animated:(BOOL)animated -{ - ASDisplayNodeAssertMainThread(); - - indexPath = [self convertIndexPathFromTableNode:indexPath waitingIfNeeded:YES]; - if (indexPath != nil) { - [super scrollToRowAtIndexPath:indexPath atScrollPosition:scrollPosition animated:animated]; - } else { - NSLog(@"Warning: Ignoring request to scroll to row at index path %@ because the item did not reach the table view.", indexPath); - } -} - /** * TODO: This method was built when the distinction between data source * index paths and view index paths was unclear. For compatibility, it diff --git a/AsyncDisplayKit/ASTableViewInternal.h b/AsyncDisplayKit/ASTableViewInternal.h index d8f4afdcf2..0a9cbf63aa 100644 --- a/AsyncDisplayKit/ASTableViewInternal.h +++ b/AsyncDisplayKit/ASTableViewInternal.h @@ -37,4 +37,12 @@ /// Set YES and we'll log every time we call [super insertRows…] etc @property (nonatomic) BOOL test_enableSuperUpdateCallLogging; +/** + * Attempt to get the view-layer index path for the row with the given index path. + * + * @param indexPath The index path of the row. + * @param wait If the item hasn't reached the view yet, this attempts to wait for updates to commit. + */ +- (NSIndexPath *)convertIndexPathFromTableNode:(NSIndexPath *)indexPath waitingIfNeeded:(BOOL)wait; + @end diff --git a/AsyncDisplayKit/Details/ASCollectionInternal.h b/AsyncDisplayKit/Details/ASCollectionInternal.h index c76238ef70..1b4e7cc7a3 100644 --- a/AsyncDisplayKit/Details/ASCollectionInternal.h +++ b/AsyncDisplayKit/Details/ASCollectionInternal.h @@ -25,6 +25,15 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, weak, readwrite) ASCollectionNode *collectionNode; @property (nonatomic, strong, readonly) ASDataController *dataController; @property (nonatomic, strong, readonly) ASRangeController *rangeController; + +/** + * Attempt to get the view-layer index path for the item with the given index path. + * + * @param indexPath The index path of the item. + * @param wait If the item hasn't reached the view yet, this attempts to wait for updates to commit. + */ +- (nullable NSIndexPath *)convertIndexPathFromCollectionNode:(NSIndexPath *)indexPath waitingIfNeeded:(BOOL)wait; + @end NS_ASSUME_NONNULL_END From eb6cf0689d08fd39fac6a50819b2673f93d07f39 Mon Sep 17 00:00:00 2001 From: Michael Schneider Date: Wed, 26 Oct 2016 17:17:09 -0700 Subject: [PATCH 47/59] Only throw if ASLayoutElement style width or height are ASDimensionUnitFraction (#2484) --- AsyncDisplayKit/Layout/ASLayoutElement.mm | 4 ++-- AsyncDisplayKitTests/ASLayoutElementStyleTests.m | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/AsyncDisplayKit/Layout/ASLayoutElement.mm b/AsyncDisplayKit/Layout/ASLayoutElement.mm index affa57314b..cad4cee86b 100644 --- a/AsyncDisplayKit/Layout/ASLayoutElement.mm +++ b/AsyncDisplayKit/Layout/ASLayoutElement.mm @@ -257,12 +257,12 @@ do {\ - (CGSize)preferredSize { ASDN::MutexLocker l(__instanceLock__); - if (_size.width.unit != ASDimensionUnitPoints) { + if (_size.width.unit == ASDimensionUnitFraction) { NSCAssert(NO, @"Cannot get preferredSize of element with fractional width. Width: %@.", NSStringFromASDimension(_size.width)); return CGSizeZero; } - if (_size.height.unit != ASDimensionUnitPoints) { + if (_size.height.unit == ASDimensionUnitFraction) { NSCAssert(NO, @"Cannot get preferredSize of element with fractional height. Height: %@.", NSStringFromASDimension(_size.height)); return CGSizeZero; } diff --git a/AsyncDisplayKitTests/ASLayoutElementStyleTests.m b/AsyncDisplayKitTests/ASLayoutElementStyleTests.m index e2551f6cfd..5a7e7cbe8b 100644 --- a/AsyncDisplayKitTests/ASLayoutElementStyleTests.m +++ b/AsyncDisplayKitTests/ASLayoutElementStyleTests.m @@ -58,6 +58,8 @@ { ASLayoutElementStyle *style = [ASLayoutElementStyle new]; + ASXCTAssertEqualSizes(style.preferredSize, CGSizeZero); + CGSize size = CGSizeMake(100, 100); style.preferredSize = size; @@ -78,7 +80,7 @@ { ASLayoutElementStyle *style = [ASLayoutElementStyle new]; - XCTAssertThrows(style.preferredSize); + XCTAssertNoThrow(style.preferredSize); style.width = ASDimensionMake(ASDimensionUnitFraction, 0.5); XCTAssertThrows(style.preferredSize); From c0125010c11e3f4ce7c8ee1e5a8e92c91d64a63e Mon Sep 17 00:00:00 2001 From: Adlai Holler Date: Thu, 27 Oct 2016 11:48:49 -0700 Subject: [PATCH 48/59] Workaround iOS 7 text drawing bug (#2492) --- AsyncDisplayKit/TextKit/ASTextKitRenderer.mm | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/AsyncDisplayKit/TextKit/ASTextKitRenderer.mm b/AsyncDisplayKit/TextKit/ASTextKitRenderer.mm index 4a6f5978c0..d8ce5f84b5 100755 --- a/AsyncDisplayKit/TextKit/ASTextKitRenderer.mm +++ b/AsyncDisplayKit/TextKit/ASTextKitRenderer.mm @@ -265,7 +265,12 @@ static NSCharacterSet *_defaultAvoidTruncationCharacterSet() // If we use default options, we can use NSAttributedString for a // fast path. if (self.canUseFastPath) { - [_attributes.attributedString drawWithRect:shadowInsetBounds options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingTruncatesLastVisibleLine context:self.stringDrawingContext]; + CGRect drawingBounds = shadowInsetBounds; + // Add a fudge-factor to the height, to workaround a bug in iOS 7 + if (AS_AT_LEAST_IOS8 == NO) { + drawingBounds.size.height += 3; + } + [_attributes.attributedString drawWithRect:drawingBounds options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingTruncatesLastVisibleLine context:self.stringDrawingContext]; } else { BOOL isScaled = [self isScaled]; [[self context] performBlockWithLockedTextKitComponents:^(NSLayoutManager *layoutManager, NSTextStorage *textStorage, NSTextContainer *textContainer) { From c67a74ec41aabbee1b39fbfc271e76799fdf558a Mon Sep 17 00:00:00 2001 From: Hannah Troisi Date: Thu, 27 Oct 2016 16:22:21 -0700 Subject: [PATCH 49/59] add descender to ASEnvironmentMergeObjectAndState() (#2494) --- AsyncDisplayKit/Private/ASEnvironmentInternal.mm | 3 +++ 1 file changed, 3 insertions(+) diff --git a/AsyncDisplayKit/Private/ASEnvironmentInternal.mm b/AsyncDisplayKit/Private/ASEnvironmentInternal.mm index 34b1aaaef0..6fbc9396e9 100644 --- a/AsyncDisplayKit/Private/ASEnvironmentInternal.mm +++ b/AsyncDisplayKit/Private/ASEnvironmentInternal.mm @@ -153,6 +153,9 @@ ASEnvironmentState ASEnvironmentMergeObjectAndState(ASEnvironmentState environme if (parentLayoutOptionsState.ascender == defaultState.ascender) { parentLayoutOptionsState.ascender = layoutOptionsState.ascender; } + if (parentLayoutOptionsState.descender == defaultState.descender) { + parentLayoutOptionsState.descender = layoutOptionsState.descender; + } if (CGPointEqualToPoint(parentLayoutOptionsState.layoutPosition, defaultState.layoutPosition)) { // For now it is unclear if we should be up-propagating sizeRange or layoutPosition. From 021f5ebdbbe61c76f996e456de85fafabb163138 Mon Sep 17 00:00:00 2001 From: Michael Schneider Date: Thu, 27 Oct 2016 16:27:09 -0700 Subject: [PATCH 50/59] Add initial snapshot tests for ASWrapperSpec (#2482) --- AsyncDisplayKit.xcodeproj/project.pbxproj | 4 ++ .../ASWrapperSpecSnapshotTests.mm | 60 ++++++++++++++++++ ...eElementsShouldSizeToLargestElement@2x.png | Bin 0 -> 1460 bytes ...ecWithOneElementShouldSizeToElement@2x.png | Bin 0 -> 526 bytes 4 files changed, 64 insertions(+) create mode 100644 AsyncDisplayKitTests/ASWrapperSpecSnapshotTests.mm create mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASWrapperSpecSnapshotTests/testWrapperSpecWithMultipleElementsShouldSizeToLargestElement@2x.png create mode 100644 AsyncDisplayKitTests/ReferenceImages_64/ASWrapperSpecSnapshotTests/testWrapperSpecWithOneElementShouldSizeToElement@2x.png diff --git a/AsyncDisplayKit.xcodeproj/project.pbxproj b/AsyncDisplayKit.xcodeproj/project.pbxproj index 7d308871c3..4fb31a5c15 100644 --- a/AsyncDisplayKit.xcodeproj/project.pbxproj +++ b/AsyncDisplayKit.xcodeproj/project.pbxproj @@ -199,6 +199,7 @@ 6959433E1D70815300B0EE1F /* ASDisplayNodeLayout.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6959433C1D70815300B0EE1F /* ASDisplayNodeLayout.mm */; }; 6959433F1D70815300B0EE1F /* ASDisplayNodeLayout.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6959433C1D70815300B0EE1F /* ASDisplayNodeLayout.mm */; }; 695943401D70815300B0EE1F /* ASDisplayNodeLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 6959433D1D70815300B0EE1F /* ASDisplayNodeLayout.h */; }; + 695BE2551DC1245C008E6EA5 /* ASWrapperSpecSnapshotTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 695BE2541DC1245C008E6EA5 /* ASWrapperSpecSnapshotTests.mm */; }; 696FCB311D6E46050093471E /* ASBackgroundLayoutSpecSnapshotTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 696FCB301D6E46050093471E /* ASBackgroundLayoutSpecSnapshotTests.mm */; }; 69708BA61D76386D005C3CF9 /* ASEqualityHashHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = 69708BA41D76386D005C3CF9 /* ASEqualityHashHelpers.h */; }; 69708BA71D76386D005C3CF9 /* ASEqualityHashHelpers.mm in Sources */ = {isa = PBXBuildFile; fileRef = 69708BA51D76386D005C3CF9 /* ASEqualityHashHelpers.mm */; }; @@ -980,6 +981,7 @@ 68FC85E81CE29C7D00EDD713 /* ASVisibilityProtocols.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASVisibilityProtocols.m; sourceTree = ""; }; 6959433C1D70815300B0EE1F /* ASDisplayNodeLayout.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASDisplayNodeLayout.mm; sourceTree = ""; }; 6959433D1D70815300B0EE1F /* ASDisplayNodeLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASDisplayNodeLayout.h; sourceTree = ""; }; + 695BE2541DC1245C008E6EA5 /* ASWrapperSpecSnapshotTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASWrapperSpecSnapshotTests.mm; sourceTree = ""; }; 696FCB301D6E46050093471E /* ASBackgroundLayoutSpecSnapshotTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASBackgroundLayoutSpecSnapshotTests.mm; sourceTree = ""; }; 69708BA41D76386D005C3CF9 /* ASEqualityHashHelpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASEqualityHashHelpers.h; path = TextKit/ASEqualityHashHelpers.h; sourceTree = ""; }; 69708BA51D76386D005C3CF9 /* ASEqualityHashHelpers.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ASEqualityHashHelpers.mm; path = TextKit/ASEqualityHashHelpers.mm; sourceTree = ""; }; @@ -1429,6 +1431,7 @@ 052EE06A1A15A0D8002C6279 /* TestResources */, 2538B6F21BC5D2A2003CA0B4 /* ASCollectionViewFlowLayoutInspectorTests.m */, 69FEE53C1D95A9AF0086F066 /* ASLayoutElementStyleTests.m */, + 695BE2541DC1245C008E6EA5 /* ASWrapperSpecSnapshotTests.mm */, ); path = AsyncDisplayKitTests; sourceTree = ""; @@ -2259,6 +2262,7 @@ CC3B208E1C3F7D0A00798563 /* ASWeakSetTests.m in Sources */, F711994E1D20C21100568860 /* ASDisplayNodeExtrasTests.m in Sources */, ACF6ED5D1B178DC700DA7C62 /* ASDimensionTests.mm in Sources */, + 695BE2551DC1245C008E6EA5 /* ASWrapperSpecSnapshotTests.mm in Sources */, CCA221D31D6FA7EF00AF6A0F /* ASViewControllerTests.m in Sources */, 058D0A38195D057000B7D73C /* ASDisplayLayerTests.m in Sources */, 2538B6F31BC5D2A2003CA0B4 /* ASCollectionViewFlowLayoutInspectorTests.m in Sources */, diff --git a/AsyncDisplayKitTests/ASWrapperSpecSnapshotTests.mm b/AsyncDisplayKitTests/ASWrapperSpecSnapshotTests.mm new file mode 100644 index 0000000000..d28b8b0fe2 --- /dev/null +++ b/AsyncDisplayKitTests/ASWrapperSpecSnapshotTests.mm @@ -0,0 +1,60 @@ +// +// ASWrapperSpecSnapshotTests.mm +// AsyncDisplayKit +// +// Copyright (c) 2014-present, Facebook, Inc. All rights reserved. +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. An additional grant +// of patent rights can be found in the PATENTS file in the same directory. +// + + +#import "ASLayoutSpecSnapshotTestsHelper.h" +#import "ASBackgroundLayoutSpec.h" + +@interface ASWrapperSpecSnapshotTests : ASLayoutSpecSnapshotTestCase +@end + +@implementation ASWrapperSpecSnapshotTests + +- (void)setUp +{ + [super setUp]; + + self.recordMode = NO; +} + +- (void)testWrapperSpecWithOneElementShouldSizeToElement +{ + ASDisplayNode *child = ASDisplayNodeWithBackgroundColor([UIColor redColor], {50, 50}); + + ASSizeRange sizeRange = ASSizeRangeMake(CGSizeZero, CGSizeMake(INFINITY, INFINITY)); + [self testWithChildren:@[child] sizeRange:sizeRange identifier:nil]; +} + +- (void)testWrapperSpecWithMultipleElementsShouldSizeToLargestElement +{ + ASDisplayNode *firstChild = ASDisplayNodeWithBackgroundColor([UIColor redColor], {50, 50}); + ASDisplayNode *secondChild = ASDisplayNodeWithBackgroundColor([UIColor greenColor], {100, 100}); + + ASSizeRange sizeRange = ASSizeRangeMake(CGSizeZero, CGSizeMake(INFINITY, INFINITY)); + [self testWithChildren:@[secondChild, firstChild] sizeRange:sizeRange identifier:nil]; +} + +- (void)testWithChildren:(NSArray *)children sizeRange:(ASSizeRange)sizeRange identifier:(NSString *)identifier +{ + ASDisplayNode *backgroundNode = ASDisplayNodeWithBackgroundColor([UIColor whiteColor]); + + NSMutableArray *subnodes = [NSMutableArray arrayWithArray:children]; + [subnodes insertObject:backgroundNode atIndex:0]; + + ASLayoutSpec *layoutSpec = + [ASBackgroundLayoutSpec backgroundLayoutSpecWithChild: + [ASWrapperLayoutSpec + wrapperWithLayoutElements:children] + background:backgroundNode]; + + [self testLayoutSpec:layoutSpec sizeRange:sizeRange subnodes:subnodes identifier:identifier]; +} + +@end diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASWrapperSpecSnapshotTests/testWrapperSpecWithMultipleElementsShouldSizeToLargestElement@2x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASWrapperSpecSnapshotTests/testWrapperSpecWithMultipleElementsShouldSizeToLargestElement@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..e34eef76c7c3d2c2cb5c6387ad5756ff0ab4c682 GIT binary patch literal 1460 zcmeAS@N?(olHy`uVBq!ia0vp^CqS5k4M?tyST_$yF%}28J29*~C-V}>;VkfoEM{O3 zQw3p0&mff#KtY*I7yl3-%>=|CkOIUSP#VZ)Hq~|x6a>_0%0XTR10JT0Z}yj1 zIp#G++5C)bnkmY};@7y@K!%B>jHiX6QJ~{gy?{c30t-irL&&{m21aH@2L+ZzpX69L zBsdtE6a}V!S8zDsz#+iVxMB}GBNLlbg9C@lQ(F!J0|6!$Ck3tdjtvcs0ty05ftCDB lEKnn>M~xiZVfiEO0b`wignp|vd$@?2>|1OuRZ_( literal 0 HcmV?d00001 diff --git a/AsyncDisplayKitTests/ReferenceImages_64/ASWrapperSpecSnapshotTests/testWrapperSpecWithOneElementShouldSizeToElement@2x.png b/AsyncDisplayKitTests/ReferenceImages_64/ASWrapperSpecSnapshotTests/testWrapperSpecWithOneElementShouldSizeToElement@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d63856e6ec17b934022ffbb0b9e254e6bfbe9b78 GIT binary patch literal 526 zcmeAS@N?(olHy`uVBq!ia0vp^DImHB6fKg`&kUr??;uuoF_~z;rk`?U40~SN^q>ua=g* QK%X#py85}Sb4q9e0KaFr)Bpeg literal 0 HcmV?d00001 From 4e32cf638849dd4ee4b012abddf514f5829b3a97 Mon Sep 17 00:00:00 2001 From: Michael Schneider Date: Thu, 27 Oct 2016 16:28:47 -0700 Subject: [PATCH 51/59] Rewrite layoutSpecThatFits: in ASDKgram (#2402) --- examples/ASDKgram/Sample/CommentsNode.m | 10 +- examples/ASDKgram/Sample/PhotoCellNode.m | 134 ++++++++++++++--------- 2 files changed, 90 insertions(+), 54 deletions(-) diff --git a/examples/ASDKgram/Sample/CommentsNode.m b/examples/ASDKgram/Sample/CommentsNode.m index 0d3b936c4e..67859bd37f 100644 --- a/examples/ASDKgram/Sample/CommentsNode.m +++ b/examples/ASDKgram/Sample/CommentsNode.m @@ -43,10 +43,12 @@ - (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize { - ASStackLayoutSpec *verticalStack = [ASStackLayoutSpec verticalStackLayoutSpec]; - verticalStack.spacing = INTER_COMMENT_SPACING; - verticalStack.children = [_commentNodes copy]; - return verticalStack; + return [ASStackLayoutSpec + stackLayoutSpecWithDirection:ASStackLayoutDirectionVertical + spacing:INTER_COMMENT_SPACING + justifyContent:ASStackLayoutJustifyContentStart + alignItems:ASStackLayoutAlignItemsStretch + children:[_commentNodes copy]]; } #pragma mark - Instance Methods diff --git a/examples/ASDKgram/Sample/PhotoCellNode.m b/examples/ASDKgram/Sample/PhotoCellNode.m index 2926b3296e..176cf4b608 100644 --- a/examples/ASDKgram/Sample/PhotoCellNode.m +++ b/examples/ASDKgram/Sample/PhotoCellNode.m @@ -91,7 +91,8 @@ _photoDescriptionLabel.maximumNumberOfLines = 3; _photoCommentsView = [[CommentsNode alloc] init]; - _photoCommentsView.shouldRasterizeDescendants = YES; + // For now disable shouldRasterizeDescendants as it will throw an assertion: 'Node should always be marked invisible before deallocating. ...' + //_photoCommentsView.shouldRasterizeDescendants = YES; // instead of adding everything addSubnode: self.automaticallyManagesSubnodes = YES; @@ -112,55 +113,89 @@ - (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize { - // username / photo location header vertical stack - _photoLocationLabel.style.flexShrink = 1.0; - _userNameLabel.style.flexShrink = 1.0; - - ASStackLayoutSpec *headerSubStack = [ASStackLayoutSpec verticalStackLayoutSpec]; - headerSubStack.style.flexShrink = 1.0; - headerSubStack.children = _photoLocationLabel.attributedText ? @[_userNameLabel, _photoLocationLabel] - : @[_userNameLabel]; - // header stack - - // constrain avatar image frame size - _userAvatarImageView.style.preferredSize = CGSizeMake(USER_IMAGE_HEIGHT, USER_IMAGE_HEIGHT); - _photoTimeIntervalSincePostLabel.style.spacingBefore = HORIZONTAL_BUFFER; // to remove double spaces around spacer - - ASLayoutSpec *spacer = [[ASLayoutSpec alloc] init]; // FIXME: long locations overflow post time - set max size? - spacer.style.flexGrow = 1.0; - - UIEdgeInsets avatarInsets = UIEdgeInsetsMake(HORIZONTAL_BUFFER, 0, HORIZONTAL_BUFFER, HORIZONTAL_BUFFER); - ASInsetLayoutSpec *avatarInset = [ASInsetLayoutSpec insetLayoutSpecWithInsets:avatarInsets child:_userAvatarImageView]; + return + // Main stack + [ASStackLayoutSpec + stackLayoutSpecWithDirection:ASStackLayoutDirectionVertical + spacing:0 + justifyContent:ASStackLayoutJustifyContentStart + alignItems:ASStackLayoutAlignItemsStretch + children:@[ - ASStackLayoutSpec *headerStack = [ASStackLayoutSpec horizontalStackLayoutSpec]; - headerStack.alignItems = ASStackLayoutAlignItemsCenter; // center items vertically in horizontal stack - headerStack.justifyContent = ASStackLayoutJustifyContentStart; // justify content to the left side of the header stack - headerStack.children = @[avatarInset, headerSubStack, spacer, _photoTimeIntervalSincePostLabel]; - - // header inset stack - UIEdgeInsets insets = UIEdgeInsetsMake(0, HORIZONTAL_BUFFER, 0, HORIZONTAL_BUFFER); - ASInsetLayoutSpec *headerWithInset = [ASInsetLayoutSpec insetLayoutSpecWithInsets:insets child:headerStack]; - - // footer stack - ASStackLayoutSpec *footerStack = [ASStackLayoutSpec verticalStackLayoutSpec]; - footerStack.spacing = VERTICAL_BUFFER; - footerStack.children = @[_photoLikesLabel, _photoDescriptionLabel, _photoCommentsView]; - - // footer inset stack - UIEdgeInsets footerInsets = UIEdgeInsetsMake(VERTICAL_BUFFER, HORIZONTAL_BUFFER, VERTICAL_BUFFER, HORIZONTAL_BUFFER); - ASInsetLayoutSpec *footerWithInset = [ASInsetLayoutSpec insetLayoutSpecWithInsets:footerInsets child:footerStack]; - - // vertical stack - CGFloat cellWidth = constrainedSize.max.width; - - // constrain photo frame size - _photoImageView.style.preferredSize = CGSizeMake(cellWidth, cellWidth); - - ASStackLayoutSpec *verticalStack = [ASStackLayoutSpec verticalStackLayoutSpec]; - verticalStack.alignItems = ASStackLayoutAlignItemsStretch; // stretch headerStack to fill horizontal space - verticalStack.children = @[headerWithInset, _photoImageView, footerWithInset]; - - return verticalStack; + // Header stack with inset + [ASInsetLayoutSpec + insetLayoutSpecWithInsets:UIEdgeInsetsMake(0, HORIZONTAL_BUFFER, 0, HORIZONTAL_BUFFER) + child: + // Header stack + [ASStackLayoutSpec + stackLayoutSpecWithDirection:ASStackLayoutDirectionHorizontal + spacing:0.0 + justifyContent:ASStackLayoutJustifyContentStart + alignItems:ASStackLayoutAlignItemsCenter + children:@[ + // Avatar image with inset + [ASInsetLayoutSpec + insetLayoutSpecWithInsets:UIEdgeInsetsMake(HORIZONTAL_BUFFER, 0, HORIZONTAL_BUFFER, HORIZONTAL_BUFFER) + child: + [_userAvatarImageView styledWithBlock:^(ASLayoutElementStyle *style) { + style.preferredSize = CGSizeMake(USER_IMAGE_HEIGHT, USER_IMAGE_HEIGHT); + }] + ], + // User and photo location stack + [[ASStackLayoutSpec + stackLayoutSpecWithDirection:ASStackLayoutDirectionVertical + spacing:0.0 + justifyContent:ASStackLayoutJustifyContentStart + alignItems:ASStackLayoutAlignItemsStretch + children:_photoLocationLabel.attributedText ? @[ + [_userNameLabel styledWithBlock:^(ASLayoutElementStyle *style) { + style.flexShrink = 1.0; + }], + [_photoLocationLabel styledWithBlock:^(ASLayoutElementStyle *style) { + style.flexShrink = 1.0; + }] + ] : + @[ + [_userNameLabel styledWithBlock:^(ASLayoutElementStyle *style) { + style.flexShrink = 1.0; + }] + ]] + styledWithBlock:^(ASLayoutElementStyle *style) { + style.flexShrink = 1.0; + }], + // Spacer between user / photo location and photo time inverval + [[ASLayoutSpec new] styledWithBlock:^(ASLayoutElementStyle *style) { + style.flexGrow = 1.0; + }], + // Photo and time interval node + [_photoTimeIntervalSincePostLabel styledWithBlock:^(ASLayoutElementStyle *style) { + // to remove double spaces around spacer + style.spacingBefore = HORIZONTAL_BUFFER; + }] + ]] + ], + + // Center photo with ratio + [ASRatioLayoutSpec + ratioLayoutSpecWithRatio:1.0 + child:_photoImageView], + + // Footer stack with inset + [ASInsetLayoutSpec + insetLayoutSpecWithInsets:UIEdgeInsetsMake(VERTICAL_BUFFER, HORIZONTAL_BUFFER, VERTICAL_BUFFER, HORIZONTAL_BUFFER) + child: + [ASStackLayoutSpec + stackLayoutSpecWithDirection:ASStackLayoutDirectionVertical + spacing:VERTICAL_BUFFER + justifyContent:ASStackLayoutJustifyContentStart + alignItems:ASStackLayoutAlignItemsStretch + children:@[ + _photoLikesLabel, + _photoDescriptionLabel, + _photoCommentsView + ]] + ] + ]]; } #pragma mark - Instance Methods @@ -181,7 +216,6 @@ ASTextNode *textNode = [[ASTextNode alloc] init]; textNode.layerBacked = YES; textNode.attributedText = attributedString; - return textNode; } From 54cda5fdbb14c9c6235e2dbe1a51e05f5ee9abd3 Mon Sep 17 00:00:00 2001 From: george-gw Date: Fri, 28 Oct 2016 01:56:00 +0200 Subject: [PATCH 52/59] [ASCellNode] Added indexPath property. (#2468) * [ASCellNode] Added indexPath property. * [ASCellNode] Cached the type of scrollView we're using in the node, and placed that logic in setScrollView. * [ASCellNode] Removed table and collection view from indexPath, since they return the index paths from the view-space. * Changed the logic for getting indexPath so that it works even when the cell is not displayed. * [VerticalWithinHorizontalScrolling] Explicitally synthesized indexPath property. --- AsyncDisplayKit/ASCellNode+Internal.h | 2 + AsyncDisplayKit/ASCellNode.h | 14 +++++++ AsyncDisplayKit/ASCellNode.mm | 32 +++++++++++++++ .../Details/ASCollectionDataController.mm | 16 ++++---- AsyncDisplayKit/Details/ASDataController.mm | 10 ++--- .../Details/ASIndexedNodeContext.h | 3 +- .../Details/ASIndexedNodeContext.mm | 6 ++- AsyncDisplayKitTests/ASCollectionViewTests.mm | 39 +++++++++++++++++++ .../Sample/RandomCoreGraphicsNode.m | 2 + 9 files changed, 106 insertions(+), 18 deletions(-) diff --git a/AsyncDisplayKit/ASCellNode+Internal.h b/AsyncDisplayKit/ASCellNode+Internal.h index 0bf032b0fb..99066aa123 100644 --- a/AsyncDisplayKit/ASCellNode+Internal.h +++ b/AsyncDisplayKit/ASCellNode+Internal.h @@ -63,6 +63,8 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, copy, nullable) NSIndexPath *cachedIndexPath; +@property (weak, nonatomic, nullable) ASDisplayNode *owningNode; + @end NS_ASSUME_NONNULL_END diff --git a/AsyncDisplayKit/ASCellNode.h b/AsyncDisplayKit/ASCellNode.h index 003e19da2e..0a6ccf3fb3 100644 --- a/AsyncDisplayKit/ASCellNode.h +++ b/AsyncDisplayKit/ASCellNode.h @@ -108,6 +108,20 @@ typedef NS_ENUM(NSUInteger, ASCellNodeVisibilityEvent) { */ @property (nonatomic, assign, getter=isHighlighted) BOOL highlighted; +/** + * The current index path of this cell node, or @c nil if this node is + * not a valid item inside a table node or collection node. + * + * @note This property must be accessed on the main thread. + */ +@property (nonatomic, readonly, nullable) NSIndexPath *indexPath; + +/** + * The owning node (ASCollectionNode/ASTableNode) of this cell node, or @c nil if this node is + * not a valid item inside a table node or collection node or if those nodes are nil. + */ +@property (weak, nonatomic, readonly, nullable) ASDisplayNode *owningNode; + /* * ASCellNode must forward touch events in order for UITableView and UICollectionView tap handling to work. Overriding * these methods (e.g. for highlighting) requires the super method be called. diff --git a/AsyncDisplayKit/ASCellNode.mm b/AsyncDisplayKit/ASCellNode.mm index 2e14030c92..84c81b6bf6 100644 --- a/AsyncDisplayKit/ASCellNode.mm +++ b/AsyncDisplayKit/ASCellNode.mm @@ -36,6 +36,12 @@ ASDisplayNode *_viewControllerNode; UIViewController *_viewController; BOOL _suspendInteractionDelegate; + + struct { + unsigned int isTableNode:1; + unsigned int isCollectionNode:1; + } _owningNodeType; + } @end @@ -186,6 +192,19 @@ static NSMutableSet *__cellClassesForVisibilityNotifications = nil; // See +init } } +- (void)setOwningNode:(ASDisplayNode *)owningNode +{ + _owningNode = owningNode; + + memset(&_owningNodeType, 0, sizeof(_owningNodeType)); + + if ([owningNode isKindOfClass:[ASTableNode class]]) { + _owningNodeType.isTableNode = 1; + } else if ([owningNode isKindOfClass:[ASCollectionNode class]]) { + _owningNodeType.isCollectionNode = 1; + } +} + - (void)__setSelectedFromUIKit:(BOOL)selected; { if (selected != _selected) { @@ -204,6 +223,19 @@ static NSMutableSet *__cellClassesForVisibilityNotifications = nil; // See +init } } +- (NSIndexPath *)indexPath +{ + ASDisplayNodeAssertMainThread(); + + if (_owningNodeType.isTableNode) { + return [(ASTableNode *)self.owningNode indexPathForNode:self]; + } else if (_owningNodeType.isCollectionNode) { + return [(ASCollectionNode *)self.owningNode indexPathForNode:self]; + } + + return nil; +} + #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wobjc-missing-super-calls" diff --git a/AsyncDisplayKit/Details/ASCollectionDataController.mm b/AsyncDisplayKit/Details/ASCollectionDataController.mm index 8ffa75ca0c..444d8fc7aa 100644 --- a/AsyncDisplayKit/Details/ASCollectionDataController.mm +++ b/AsyncDisplayKit/Details/ASCollectionDataController.mm @@ -233,15 +233,14 @@ - (void)_populateSupplementaryNodesOfKind:(NSString *)kind withSections:(NSIndexSet *)sections mutableContexts:(NSMutableArray *)contexts { - id environment = [self.environmentDelegate dataControllerEnvironment]; - ASEnvironmentTraitCollection environmentTraitCollection = environment.environmentTraitCollection; - + __weak id environment = [self.environmentDelegate dataControllerEnvironment]; + [sections enumerateRangesUsingBlock:^(NSRange range, BOOL * _Nonnull stop) { for (NSUInteger sec = range.location; sec < NSMaxRange(range); sec++) { NSUInteger itemCount = [self.collectionDataSource dataController:self supplementaryNodesOfKind:kind inSection:sec]; for (NSUInteger i = 0; i < itemCount; i++) { NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:sec]; - [self _populateSupplementaryNodeOfKind:kind atIndexPath:indexPath mutableContexts:contexts environmentTraitCollection:environmentTraitCollection]; + [self _populateSupplementaryNodeOfKind:kind atIndexPath:indexPath mutableContexts:contexts environment:environment]; } } }]; @@ -249,8 +248,7 @@ - (void)_populateSupplementaryNodesOfKind:(NSString *)kind atIndexPaths:(NSArray *)indexPaths mutableContexts:(NSMutableArray *)contexts { - id environment = [self.environmentDelegate dataControllerEnvironment]; - ASEnvironmentTraitCollection environmentTraitCollection = environment.environmentTraitCollection; + __weak id environment = [self.environmentDelegate dataControllerEnvironment]; NSMutableIndexSet *sections = [NSMutableIndexSet indexSet]; for (NSIndexPath *indexPath in indexPaths) { @@ -262,13 +260,13 @@ NSUInteger itemCount = [self.collectionDataSource dataController:self supplementaryNodesOfKind:kind inSection:sec]; for (NSUInteger i = 0; i < itemCount; i++) { NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:sec]; - [self _populateSupplementaryNodeOfKind:kind atIndexPath:indexPath mutableContexts:contexts environmentTraitCollection:environmentTraitCollection]; + [self _populateSupplementaryNodeOfKind:kind atIndexPath:indexPath mutableContexts:contexts environment:environment]; } } }]; } -- (void)_populateSupplementaryNodeOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath mutableContexts:(NSMutableArray *)contexts environmentTraitCollection:(ASEnvironmentTraitCollection)environmentTraitCollection +- (void)_populateSupplementaryNodeOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath mutableContexts:(NSMutableArray *)contexts environment:(id)environment { ASCellNodeBlock supplementaryCellBlock; if (_dataSourceImplementsSupplementaryNodeBlockOfKindAtIndexPath) { @@ -283,7 +281,7 @@ indexPath:indexPath supplementaryElementKind:kind constrainedSize:constrainedSize - environmentTraitCollection:environmentTraitCollection]; + environment:environment]; [contexts addObject:context]; } diff --git a/AsyncDisplayKit/Details/ASDataController.mm b/AsyncDisplayKit/Details/ASDataController.mm index 7638a4e1d4..4de4eee949 100644 --- a/AsyncDisplayKit/Details/ASDataController.mm +++ b/AsyncDisplayKit/Details/ASDataController.mm @@ -476,8 +476,7 @@ NSString * const ASDataControllerRowNodeKind = @"_ASDataControllerRowNodeKind"; { ASDisplayNodeAssertMainThread(); - id environment = [self.environmentDelegate dataControllerEnvironment]; - ASEnvironmentTraitCollection environmentTraitCollection = environment.environmentTraitCollection; + __weak id environment = [self.environmentDelegate dataControllerEnvironment]; std::vector counts = [self itemCountsFromDataSource]; NSMutableArray *contexts = [NSMutableArray array]; @@ -493,7 +492,7 @@ NSString * const ASDataControllerRowNodeKind = @"_ASDataControllerRowNodeKind"; indexPath:indexPath supplementaryElementKind:nil constrainedSize:constrainedSize - environmentTraitCollection:environmentTraitCollection]]; + environment:environment]]; } } }]; @@ -743,8 +742,7 @@ NSString * const ASDataControllerRowNodeKind = @"_ASDataControllerRowNodeKind"; NSArray *sortedIndexPaths = [indexPaths sortedArrayUsingSelector:@selector(compare:)]; NSMutableArray *contexts = [[NSMutableArray alloc] initWithCapacity:indexPaths.count]; - id environment = [self.environmentDelegate dataControllerEnvironment]; - ASEnvironmentTraitCollection environmentTraitCollection = environment.environmentTraitCollection; + __weak id environment = [self.environmentDelegate dataControllerEnvironment]; for (NSIndexPath *indexPath in sortedIndexPaths) { ASCellNodeBlock nodeBlock = [_dataSource dataController:self nodeBlockAtIndexPath:indexPath]; @@ -753,7 +751,7 @@ NSString * const ASDataControllerRowNodeKind = @"_ASDataControllerRowNodeKind"; indexPath:indexPath supplementaryElementKind:nil constrainedSize:constrainedSize - environmentTraitCollection:environmentTraitCollection]]; + environment:environment]]; } ASInsertElementsIntoMultidimensionalArrayAtIndexPaths(_nodeContexts[ASDataControllerRowNodeKind], sortedIndexPaths, contexts); diff --git a/AsyncDisplayKit/Details/ASIndexedNodeContext.h b/AsyncDisplayKit/Details/ASIndexedNodeContext.h index 6e7992135d..2bf7822221 100644 --- a/AsyncDisplayKit/Details/ASIndexedNodeContext.h +++ b/AsyncDisplayKit/Details/ASIndexedNodeContext.h @@ -24,13 +24,14 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, readonly, strong) NSIndexPath *indexPath; @property (nonatomic, readonly, copy, nullable) NSString *supplementaryElementKind; @property (nonatomic, readonly, assign) ASSizeRange constrainedSize; +@property (weak, nonatomic) id environment; @property (nonatomic, readonly, assign) ASEnvironmentTraitCollection environmentTraitCollection; - (instancetype)initWithNodeBlock:(ASCellNodeBlock)nodeBlock indexPath:(NSIndexPath *)indexPath supplementaryElementKind:(nullable NSString *)supplementaryElementKind constrainedSize:(ASSizeRange)constrainedSize - environmentTraitCollection:(ASEnvironmentTraitCollection)environmentTraitCollection; + environment:(id)environment; /** * @return The node, running the node block if necessary. The node block will be discarded diff --git a/AsyncDisplayKit/Details/ASIndexedNodeContext.mm b/AsyncDisplayKit/Details/ASIndexedNodeContext.mm index 38624e3a42..15020eecb1 100644 --- a/AsyncDisplayKit/Details/ASIndexedNodeContext.mm +++ b/AsyncDisplayKit/Details/ASIndexedNodeContext.mm @@ -31,7 +31,7 @@ indexPath:(NSIndexPath *)indexPath supplementaryElementKind:(nullable NSString *)supplementaryElementKind constrainedSize:(ASSizeRange)constrainedSize - environmentTraitCollection:(ASEnvironmentTraitCollection)environmentTraitCollection + environment:(id)environment { NSAssert(nodeBlock != nil && indexPath != nil, @"Node block and index path must not be nil"); self = [super init]; @@ -40,7 +40,8 @@ _indexPath = indexPath; _supplementaryElementKind = [supplementaryElementKind copy]; _constrainedSize = constrainedSize; - _environmentTraitCollection = environmentTraitCollection; + _environment = environment; + _environmentTraitCollection = environment.environmentTraitCollection; } return self; } @@ -57,6 +58,7 @@ } node.cachedIndexPath = _indexPath; node.supplementaryElementKind = _supplementaryElementKind; + node.owningNode = (ASDisplayNode *)_environment; ASEnvironmentStatePropagateDown(node, _environmentTraitCollection); _node = node; } diff --git a/AsyncDisplayKitTests/ASCollectionViewTests.mm b/AsyncDisplayKitTests/ASCollectionViewTests.mm index f19d8fa0fb..f0f509195e 100644 --- a/AsyncDisplayKitTests/ASCollectionViewTests.mm +++ b/AsyncDisplayKitTests/ASCollectionViewTests.mm @@ -504,6 +504,45 @@ } } +- (void)testCellNodeIndexPathConsistency +{ + updateValidationTestPrologue + + // Test with a visible cell + NSIndexPath *indexPath = [NSIndexPath indexPathForItem:2 inSection:0]; + ASCellNode *cell = [cn nodeForItemAtIndexPath:indexPath]; + + // Check if cell's indexPath corresponds to the indexPath being tested + XCTAssertTrue(cell.indexPath.section == indexPath.section && cell.indexPath.item == indexPath.item, @"Expected the cell's indexPath to be the same as the indexPath being tested."); + + // Remove an item prior to the cell's indexPath from the same section and check for indexPath consistency + --del->_itemCounts[indexPath.section]; + [cn deleteItemsAtIndexPaths:@[[NSIndexPath indexPathForItem:0 inSection:indexPath.section]]]; + XCTAssertTrue(cell.indexPath.section == indexPath.section && cell.indexPath.item == (indexPath.item - 1), @"Expected the cell's indexPath to be updated once a cell with a lower index is deleted."); + + // Remove the section that includes the indexPath and check if the cell's indexPath is now nil + del->_itemCounts.erase(del->_itemCounts.begin()); + [cn deleteSections:[NSIndexSet indexSetWithIndex:indexPath.section]]; + XCTAssertNil(cell.indexPath, @"Expected the cell's indexPath to be nil once the section that contains the node is deleted."); + + // Run the same tests but with a non-displayed cell + indexPath = [NSIndexPath indexPathForItem:2 inSection:(del->_itemCounts.size() - 1)]; + cell = [cn nodeForItemAtIndexPath:indexPath]; + + // Check if cell's indexPath corresponds to the indexPath being tested + XCTAssertTrue(cell.indexPath.section == indexPath.section && cell.indexPath.item == indexPath.item, @"Expected the cell's indexPath to be the same as the indexPath in question."); + + // Remove an item prior to the cell's indexPath from the same section and check for indexPath consistency + --del->_itemCounts[indexPath.section]; + [cn deleteItemsAtIndexPaths:@[[NSIndexPath indexPathForItem:0 inSection:indexPath.section]]]; + XCTAssertTrue(cell.indexPath.section == indexPath.section && cell.indexPath.item == (indexPath.item - 1), @"Expected the cell's indexPath to be updated once a cell with a lower index is deleted."); + + // Remove the section that includes the indexPath and check if the cell's indexPath is now nil + del->_itemCounts.pop_back(); + [cn deleteSections:[NSIndexSet indexSetWithIndex:indexPath.section]]; + XCTAssertNil(cell.indexPath, @"Expected the cell's indexPath to be nil once the section that contains the node is deleted."); +} + /** * https://github.com/facebook/AsyncDisplayKit/issues/2011 * diff --git a/examples/VerticalWithinHorizontalScrolling/Sample/RandomCoreGraphicsNode.m b/examples/VerticalWithinHorizontalScrolling/Sample/RandomCoreGraphicsNode.m index 74dd517084..16d40df7aa 100644 --- a/examples/VerticalWithinHorizontalScrolling/Sample/RandomCoreGraphicsNode.m +++ b/examples/VerticalWithinHorizontalScrolling/Sample/RandomCoreGraphicsNode.m @@ -22,6 +22,8 @@ @implementation RandomCoreGraphicsNode +@synthesize indexPath=_indexPath; + + (UIColor *)randomColor { CGFloat hue = ( arc4random() % 256 / 256.0 ); // 0.0 to 1.0 From 8add4619cf0473c907deecae3bf1e2cc904b3479 Mon Sep 17 00:00:00 2001 From: Adlai Holler Date: Fri, 28 Oct 2016 09:42:45 -0700 Subject: [PATCH 53/59] Reduce Traffic to Table/Collection View When Updating (#2496) * Improve the call pattern when loading table/collection data * When deleting sections, no need to delete rows first * Clean up a couple things --- AsyncDisplayKit/Details/ASDataController.mm | 26 +++-- AsyncDisplayKitTests/ASTableViewTests.m | 120 ++++++++++++++++++++ Podfile | 1 + 3 files changed, 138 insertions(+), 9 deletions(-) diff --git a/AsyncDisplayKit/Details/ASDataController.mm b/AsyncDisplayKit/Details/ASDataController.mm index 4de4eee949..75be3cb8b9 100644 --- a/AsyncDisplayKit/Details/ASDataController.mm +++ b/AsyncDisplayKit/Details/ASDataController.mm @@ -427,12 +427,16 @@ NSString * const ASDataControllerRowNodeKind = @"_ASDataControllerRowNodeKind"; LOG(@"Edit Transaction - reloadData"); // Remove everything that existed before the reload, now that we're ready to insert replacements - NSMutableArray *editingNodes = _editingNodes[ASDataControllerRowNodeKind]; - NSUInteger editingNodesSectionCount = editingNodes.count; - - if (editingNodesSectionCount) { - NSIndexSet *indexSet = [[NSIndexSet alloc] initWithIndexesInRange:NSMakeRange(0, editingNodesSectionCount)]; - [self _deleteNodesAtIndexPaths:ASIndexPathsForTwoDimensionalArray(editingNodes) withAnimationOptions:animationOptions]; + NSUInteger oldSectionCount = [_editingNodes[ASDataControllerRowNodeKind] count]; + + // If we have old sections, we should delete them inside beginUpdates/endUpdates with inserting the new ones. + if (oldSectionCount) { + // -beginUpdates + [_mainSerialQueue performBlockOnMainThread:^{ + [_delegate dataControllerBeginUpdates:self]; + }]; + + NSIndexSet *indexSet = [[NSIndexSet alloc] initWithIndexesInRange:NSMakeRange(0, oldSectionCount)]; [self _deleteSectionsAtIndexSet:indexSet withAnimationOptions:animationOptions]; } @@ -445,6 +449,13 @@ NSString * const ASDataControllerRowNodeKind = @"_ASDataControllerRowNodeKind"; } [self _insertSections:sections atIndexSet:sectionIndexes withAnimationOptions:animationOptions]; + if (oldSectionCount) { + // -endUpdates + [_mainSerialQueue performBlockOnMainThread:^{ + [_delegate dataController:self endUpdatesAnimated:NO completion:nil]; + }]; + } + [self _batchLayoutAndInsertNodesFromContexts:newContexts withAnimationOptions:animationOptions]; if (completion) { @@ -623,9 +634,6 @@ NSString * const ASDataControllerRowNodeKind = @"_ASDataControllerRowNodeKind"; // remove elements LOG(@"Edit Transaction - deleteSections: %@", sections); - NSArray *indexPaths = ASIndexPathsForMultidimensionalArrayAtIndexSet(_editingNodes[ASDataControllerRowNodeKind], sections); - - [self _deleteNodesAtIndexPaths:indexPaths withAnimationOptions:animationOptions]; [self _deleteSectionsAtIndexSet:sections withAnimationOptions:animationOptions]; }); } diff --git a/AsyncDisplayKitTests/ASTableViewTests.m b/AsyncDisplayKitTests/ASTableViewTests.m index 2b2b480aef..752a9f94d4 100644 --- a/AsyncDisplayKitTests/ASTableViewTests.m +++ b/AsyncDisplayKitTests/ASTableViewTests.m @@ -17,6 +17,7 @@ #import "ASCellNode.h" #import "ASTableNode.h" #import "ASTableView+Undeprecated.h" +#import #define NumberOfSections 10 #define NumberOfRowsPerSection 20 @@ -36,6 +37,13 @@ @end +@interface UITableView (Testing) +// This will start recording all editing calls to UITableView +// into the provided array. +// Make sure to call [UITableView deswizzleInstanceMethods] to reset this. ++ (void)as_recordEditingCallsIntoArray:(NSMutableArray *)selectors; +@end + @interface ASTestTableView : ASTableView @property (nonatomic, copy) void (^willDeallocBlock)(ASTableView *tableView); @end @@ -544,4 +552,116 @@ XCTAssert([node conformsToProtocol:@protocol(ASRangeControllerUpdateRangeProtocol)]); } +- (void)testThatInitialDataLoadHappensInOneShot +{ + NSMutableArray *selectors = [NSMutableArray array]; + ASTableNode *node = [[ASTableNode alloc] initWithStyle:UITableViewStylePlain]; + + ASTableViewFilledDataSource *dataSource = [ASTableViewFilledDataSource new]; + node.frame = CGRectMake(0, 0, 100, 100); + + node.dataSource = dataSource; + node.delegate = dataSource; + + [UITableView as_recordEditingCallsIntoArray:selectors]; + XCTAssertGreaterThan(node.numberOfSections, 0); + [node waitUntilAllUpdatesAreCommitted]; + XCTAssertGreaterThan(node.view.numberOfSections, 0); + + // Assert that the beginning of the call pattern is correct. + // There is currently noise that comes after that we will allow for this test. + NSArray *expectedSelectors = @[ NSStringFromSelector(@selector(reloadData)), + NSStringFromSelector(@selector(insertSections:withRowAnimation:)), + NSStringFromSelector(@selector(insertRowsAtIndexPaths:withRowAnimation:))]; + NSArray *firstSelectors = [selectors subarrayWithRange:NSMakeRange(0, expectedSelectors.count)]; + XCTAssertEqualObjects(firstSelectors, expectedSelectors); + + [UITableView deswizzleAllInstanceMethods]; +} + +- (void)testThatReloadDataHappensInOneShot +{ + NSMutableArray *selectors = [NSMutableArray array]; + ASTableNode *node = [[ASTableNode alloc] initWithStyle:UITableViewStylePlain]; + + ASTableViewFilledDataSource *dataSource = [ASTableViewFilledDataSource new]; + node.frame = CGRectMake(0, 0, 100, 100); + + node.dataSource = dataSource; + node.delegate = dataSource; + + // Load initial data. + XCTAssertGreaterThan(node.numberOfSections, 0); + [node waitUntilAllUpdatesAreCommitted]; + XCTAssertGreaterThan(node.view.numberOfSections, 0); + + // Reload data. + [UITableView as_recordEditingCallsIntoArray:selectors]; + [node reloadData]; + [node waitUntilAllUpdatesAreCommitted]; + + // Assert that the beginning of the call pattern is correct. + // There is currently noise that comes after that we will allow for this test. + NSArray *expectedSelectors = @[NSStringFromSelector(@selector(reloadData)), + NSStringFromSelector(@selector(beginUpdates)), + NSStringFromSelector(@selector(deleteSections:withRowAnimation:)), + NSStringFromSelector(@selector(insertSections:withRowAnimation:)), + NSStringFromSelector(@selector(endUpdates)), + NSStringFromSelector(@selector(insertRowsAtIndexPaths:withRowAnimation:))]; + NSArray *firstSelectors = [selectors subarrayWithRange:NSMakeRange(0, expectedSelectors.count)]; + XCTAssertEqualObjects(firstSelectors, expectedSelectors); + + [UITableView deswizzleAllInstanceMethods]; +} + +@end + +@implementation UITableView (Testing) + ++ (void)as_recordEditingCallsIntoArray:(NSMutableArray *)selectors +{ + [UITableView swizzleInstanceMethod:@selector(reloadData) withReplacement:JGMethodReplacementProviderBlock { + return JGMethodReplacement(void, UITableView *) { + JGOriginalImplementation(void); + [selectors addObject:NSStringFromSelector(_cmd)]; + }; + }]; + [UITableView swizzleInstanceMethod:@selector(beginUpdates) withReplacement:JGMethodReplacementProviderBlock { + return JGMethodReplacement(void, UITableView *) { + JGOriginalImplementation(void); + [selectors addObject:NSStringFromSelector(_cmd)]; + }; + }]; + [UITableView swizzleInstanceMethod:@selector(endUpdates) withReplacement:JGMethodReplacementProviderBlock { + return JGMethodReplacement(void, UITableView *) { + JGOriginalImplementation(void); + [selectors addObject:NSStringFromSelector(_cmd)]; + }; + }]; + [UITableView swizzleInstanceMethod:@selector(insertRowsAtIndexPaths:withRowAnimation:) withReplacement:JGMethodReplacementProviderBlock { + return JGMethodReplacement(void, UITableView *, NSArray *indexPaths, UITableViewRowAnimation anim) { + JGOriginalImplementation(void, indexPaths, anim); + [selectors addObject:NSStringFromSelector(_cmd)]; + }; + }]; + [UITableView swizzleInstanceMethod:@selector(deleteRowsAtIndexPaths:withRowAnimation:) withReplacement:JGMethodReplacementProviderBlock { + return JGMethodReplacement(void, UITableView *, NSArray *indexPaths, UITableViewRowAnimation anim) { + JGOriginalImplementation(void, indexPaths, anim); + [selectors addObject:NSStringFromSelector(_cmd)]; + }; + }]; + [UITableView swizzleInstanceMethod:@selector(insertSections:withRowAnimation:) withReplacement:JGMethodReplacementProviderBlock { + return JGMethodReplacement(void, UITableView *, NSIndexSet *indexes, UITableViewRowAnimation anim) { + JGOriginalImplementation(void, indexes, anim); + [selectors addObject:NSStringFromSelector(_cmd)]; + }; + }]; + [UITableView swizzleInstanceMethod:@selector(deleteSections:withRowAnimation:) withReplacement:JGMethodReplacementProviderBlock { + return JGMethodReplacement(void, UITableView *, NSIndexSet *indexes, UITableViewRowAnimation anim) { + JGOriginalImplementation(void, indexes, anim); + [selectors addObject:NSStringFromSelector(_cmd)]; + }; + }]; +} + @end diff --git a/Podfile b/Podfile index a625c28556..d1b954c71b 100644 --- a/Podfile +++ b/Podfile @@ -5,4 +5,5 @@ platform :ios, '7.0' target :'AsyncDisplayKitTests' do pod 'OCMock', '~> 2.2' pod 'FBSnapshotTestCase/Core', '~> 2.1' + pod 'JGMethodSwizzler', :git => 'https://github.com/JonasGessner/JGMethodSwizzler', :branch => 'master' end From 1165628905f92aa00c1605230f32953f5d7f0670 Mon Sep 17 00:00:00 2001 From: Garrett Moon Date: Fri, 28 Oct 2016 15:18:45 -0700 Subject: [PATCH 54/59] We need to ensure point dimensions are valid for sizing. (#2503) --- AsyncDisplayKit/Layout/ASDimension.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/AsyncDisplayKit/Layout/ASDimension.h b/AsyncDisplayKit/Layout/ASDimension.h index c8889d9e7f..c59c8fb6fb 100644 --- a/AsyncDisplayKit/Layout/ASDimension.h +++ b/AsyncDisplayKit/Layout/ASDimension.h @@ -102,7 +102,7 @@ ASOVERLOADABLE ASDISPLAYNODE_INLINE ASDimension ASDimensionMake(ASDimensionUnit if (unit == ASDimensionUnitAuto ) { ASDisplayNodeCAssert(value == 0, @"ASDimension auto value must be 0."); } else if (unit == ASDimensionUnitPoints) { - ASDisplayNodeCAssertPositiveReal(@"Points", value); + ASDisplayNodeCAssert(ASPointsValidForSize(value), @"ASDimension points value (%f) must be valid for size.", value); } else if (unit == ASDimensionUnitFraction) { ASDisplayNodeCAssert( 0 <= value && value <= 1.0, @"ASDimension fraction value (%f) must be between 0 and 1.", value); } @@ -132,7 +132,7 @@ ASOVERLOADABLE AS_WARN_UNUSED_RESULT extern ASDimension ASDimensionMake(NSString */ ASDISPLAYNODE_INLINE AS_WARN_UNUSED_RESULT ASDimension ASDimensionMakeWithPoints(CGFloat points) { - ASDisplayNodeCAssertPositiveReal(@"Points", points); + ASDisplayNodeCAssert(ASPointsValidForSize(points), @"ASDimension points value (%f) must be valid for size.", points); return ASDimensionMake(ASDimensionUnitPoints, points); } From e4a2637804ebcd243dc88f97e99219efdf26b09b Mon Sep 17 00:00:00 2001 From: george-gw Date: Sat, 29 Oct 2016 00:36:14 +0200 Subject: [PATCH 55/59] [Examples] Playground swift (#2425) * Added Playground-Swift with two example pages. * Added PhotoWithOutsetIconOverlay example. * Added an extra tip in swift playground. * Added HorizontalStackWithSpacer to the swift playground. * Added fileprivate for some global variables. * Added private to the setupNodes functions * Added solutions to common issues. --- .gitignore | 5 + examples/ASLayoutSpecPlayground-Swift/Podfile | 7 + .../Sample.xcodeproj/project.pbxproj | 380 ++++++++++++++++++ .../xcshareddata/xcschemes/Sample.xcscheme | 90 +++++ .../Sample/Info.plist | 24 ++ .../Sample/Sample.h | 18 + .../Contents.swift | 46 +++ .../Index.xcplaygroundpage/Contents.swift | 24 ++ .../Contents.swift | 26 ++ .../Contents.swift | 28 ++ .../Contents.swift | 31 ++ .../Sources/ASPlayground.swift | 26 ++ .../Sources/HorizontalStackWithSpacer.swift | 38 ++ .../Sources/PhotoWithInsetTextOverlay.swift | 33 ++ .../Sources/PhotoWithOutsetIconOverlay.swift | 33 ++ .../Sources/StackLayout.swift | 31 ++ .../Sample.playground/Sources/Utilities.swift | 43 ++ .../Sample.playground/contents.xcplayground | 10 + 18 files changed, 893 insertions(+) create mode 100644 examples/ASLayoutSpecPlayground-Swift/Podfile create mode 100644 examples/ASLayoutSpecPlayground-Swift/Sample.xcodeproj/project.pbxproj create mode 100644 examples/ASLayoutSpecPlayground-Swift/Sample.xcodeproj/xcshareddata/xcschemes/Sample.xcscheme create mode 100644 examples/ASLayoutSpecPlayground-Swift/Sample/Info.plist create mode 100644 examples/ASLayoutSpecPlayground-Swift/Sample/Sample.h create mode 100644 examples/ASLayoutSpecPlayground-Swift/Sample/Sample.playground/Pages/HorizontalStackWithSpacer.xcplaygroundpage/Contents.swift create mode 100644 examples/ASLayoutSpecPlayground-Swift/Sample/Sample.playground/Pages/Index.xcplaygroundpage/Contents.swift create mode 100644 examples/ASLayoutSpecPlayground-Swift/Sample/Sample.playground/Pages/PhotoWithInsetTextOverlay.xcplaygroundpage/Contents.swift create mode 100644 examples/ASLayoutSpecPlayground-Swift/Sample/Sample.playground/Pages/PhotoWithOutsetIconOverlay.xcplaygroundpage/Contents.swift create mode 100644 examples/ASLayoutSpecPlayground-Swift/Sample/Sample.playground/Pages/StackLayout.xcplaygroundpage/Contents.swift create mode 100644 examples/ASLayoutSpecPlayground-Swift/Sample/Sample.playground/Sources/ASPlayground.swift create mode 100644 examples/ASLayoutSpecPlayground-Swift/Sample/Sample.playground/Sources/HorizontalStackWithSpacer.swift create mode 100644 examples/ASLayoutSpecPlayground-Swift/Sample/Sample.playground/Sources/PhotoWithInsetTextOverlay.swift create mode 100644 examples/ASLayoutSpecPlayground-Swift/Sample/Sample.playground/Sources/PhotoWithOutsetIconOverlay.swift create mode 100644 examples/ASLayoutSpecPlayground-Swift/Sample/Sample.playground/Sources/StackLayout.swift create mode 100644 examples/ASLayoutSpecPlayground-Swift/Sample/Sample.playground/Sources/Utilities.swift create mode 100644 examples/ASLayoutSpecPlayground-Swift/Sample/Sample.playground/contents.xcplayground diff --git a/.gitignore b/.gitignore index 253f8380d5..7669d5a445 100644 --- a/.gitignore +++ b/.gitignore @@ -24,3 +24,8 @@ build *.gcov *.gcno *.gcda + +## Playgrounds +timeline.xctimeline +playground.xcworkspace + diff --git a/examples/ASLayoutSpecPlayground-Swift/Podfile b/examples/ASLayoutSpecPlayground-Swift/Podfile new file mode 100644 index 0000000000..dcbb49798f --- /dev/null +++ b/examples/ASLayoutSpecPlayground-Swift/Podfile @@ -0,0 +1,7 @@ +source 'https://github.com/CocoaPods/Specs.git' +platform :ios, '7.1' +use_frameworks! +target 'Sample' do + pod 'AsyncDisplayKit', :path => '../..' +end + diff --git a/examples/ASLayoutSpecPlayground-Swift/Sample.xcodeproj/project.pbxproj b/examples/ASLayoutSpecPlayground-Swift/Sample.xcodeproj/project.pbxproj new file mode 100644 index 0000000000..ced4aae5c4 --- /dev/null +++ b/examples/ASLayoutSpecPlayground-Swift/Sample.xcodeproj/project.pbxproj @@ -0,0 +1,380 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 5E6D34211DB4C9D000FB9B0A /* Sample.h in Headers */ = {isa = PBXBuildFile; fileRef = 5E6D341F1DB4C9D000FB9B0A /* Sample.h */; settings = {ATTRIBUTES = (Public, ); }; }; + FF896945AEA7EF2D9CD93A65 /* Pods_Sample.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EC767A9EB720B4BF08C89936 /* Pods_Sample.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 088AA6578212BE9BFBB07B70 /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = ""; }; + 3D24B17D1E4A4E7A9566C5E9 /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 5C5154389F056C672F4E9EEA /* Pods-Sample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Sample.release.xcconfig"; path = "Pods/Target Support Files/Pods-Sample/Pods-Sample.release.xcconfig"; sourceTree = ""; }; + 5E6D341D1DB4C9D000FB9B0A /* Sample.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Sample.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 5E6D341F1DB4C9D000FB9B0A /* Sample.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Sample.h; sourceTree = ""; }; + 5E6D34201DB4C9D000FB9B0A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 5E6D34251DB4CA8E00FB9B0A /* libPods-Sample.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libPods-Sample.a"; path = "Pods/../build/Debug-iphoneos/libPods-Sample.a"; sourceTree = ""; }; + 5E6D34271DB4CBAA00FB9B0A /* Sample.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = Sample.playground; sourceTree = ""; }; + C068F1D3F0CC317E895FCDAB /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.debug.xcconfig; path = "Pods/Target Support Files/Pods/Pods.debug.xcconfig"; sourceTree = ""; }; + EC767A9EB720B4BF08C89936 /* Pods_Sample.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Sample.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + FDF496F367580DF9280D36EA /* Pods-Sample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Sample.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Sample/Pods-Sample.debug.xcconfig"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 5E6D34191DB4C9D000FB9B0A /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + FF896945AEA7EF2D9CD93A65 /* Pods_Sample.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 05E2127819D4DB510098F589 = { + isa = PBXGroup; + children = ( + 5E6D341E1DB4C9D000FB9B0A /* Sample */, + 05E2128219D4DB510098F589 /* Products */, + 1A943BF0259746F18D6E423F /* Frameworks */, + 1AE410B73DA5C3BD087ACDD7 /* Pods */, + ); + indentWidth = 2; + sourceTree = ""; + tabWidth = 2; + usesTabs = 0; + }; + 05E2128219D4DB510098F589 /* Products */ = { + isa = PBXGroup; + children = ( + 5E6D341D1DB4C9D000FB9B0A /* Sample.framework */, + ); + name = Products; + sourceTree = ""; + }; + 1A943BF0259746F18D6E423F /* Frameworks */ = { + isa = PBXGroup; + children = ( + 5E6D34251DB4CA8E00FB9B0A /* libPods-Sample.a */, + 3D24B17D1E4A4E7A9566C5E9 /* libPods.a */, + EC767A9EB720B4BF08C89936 /* Pods_Sample.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 1AE410B73DA5C3BD087ACDD7 /* Pods */ = { + isa = PBXGroup; + children = ( + C068F1D3F0CC317E895FCDAB /* Pods.debug.xcconfig */, + 088AA6578212BE9BFBB07B70 /* Pods.release.xcconfig */, + FDF496F367580DF9280D36EA /* Pods-Sample.debug.xcconfig */, + 5C5154389F056C672F4E9EEA /* Pods-Sample.release.xcconfig */, + ); + name = Pods; + sourceTree = ""; + }; + 5E6D341E1DB4C9D000FB9B0A /* Sample */ = { + isa = PBXGroup; + children = ( + 5E6D341F1DB4C9D000FB9B0A /* Sample.h */, + 5E6D34201DB4C9D000FB9B0A /* Info.plist */, + 5E6D34271DB4CBAA00FB9B0A /* Sample.playground */, + ); + path = Sample; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 5E6D341A1DB4C9D000FB9B0A /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 5E6D34211DB4C9D000FB9B0A /* Sample.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 5E6D341C1DB4C9D000FB9B0A /* Sample */ = { + isa = PBXNativeTarget; + buildConfigurationList = 5E6D34221DB4C9D000FB9B0A /* Build configuration list for PBXNativeTarget "Sample" */; + buildPhases = ( + 43927A700F47FC31FA2FB429 /* [CP] Check Pods Manifest.lock */, + 5E6D34181DB4C9D000FB9B0A /* Sources */, + 5E6D34191DB4C9D000FB9B0A /* Frameworks */, + 5E6D341A1DB4C9D000FB9B0A /* Headers */, + 5E6D341B1DB4C9D000FB9B0A /* Resources */, + 0FF30A537A157312FD5042F7 /* [CP] Copy Pods Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Sample; + productName = Sample; + productReference = 5E6D341D1DB4C9D000FB9B0A /* Sample.framework */; + productType = "com.apple.product-type.framework"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 05E2127919D4DB510098F589 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0720; + ORGANIZATIONNAME = Facebook; + TargetAttributes = { + 5E6D341C1DB4C9D000FB9B0A = { + CreatedOnToolsVersion = 8.0; + ProvisioningStyle = Automatic; + }; + }; + }; + buildConfigurationList = 05E2127C19D4DB510098F589 /* Build configuration list for PBXProject "Sample" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 05E2127819D4DB510098F589; + productRefGroup = 05E2128219D4DB510098F589 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 5E6D341C1DB4C9D000FB9B0A /* Sample */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 5E6D341B1DB4C9D000FB9B0A /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 0FF30A537A157312FD5042F7 /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "[CP] Copy Pods Resources"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Sample/Pods-Sample-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; + 43927A700F47FC31FA2FB429 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "[CP] Check Pods Manifest.lock"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 5E6D34181DB4C9D000FB9B0A /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 05E212A219D4DB510098F589 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 7.1; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + }; + name = Debug; + }; + 05E212A319D4DB510098F589 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = YES; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 7.1; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 5E6D34231DB4C9D000FB9B0A /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = FDF496F367580DF9280D36EA /* Pods-Sample.debug.xcconfig */; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_SUSPICIOUS_MOVES = YES; + CODE_SIGN_IDENTITY = ""; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_NO_COMMON_BLOCKS = YES; + INFOPLIST_FILE = Sample/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + LIBRARY_SEARCH_PATHS = "$(inherited)"; + PRODUCT_BUNDLE_IDENTIFIER = com.facebook.AsyncDisplayKit.Sample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 5E6D34241DB4C9D000FB9B0A /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 5C5154389F056C672F4E9EEA /* Pods-Sample.release.xcconfig */; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_SUSPICIOUS_MOVES = YES; + CODE_SIGN_IDENTITY = ""; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_NO_COMMON_BLOCKS = YES; + INFOPLIST_FILE = Sample/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + LIBRARY_SEARCH_PATHS = "$(inherited)"; + PRODUCT_BUNDLE_IDENTIFIER = com.facebook.AsyncDisplayKit.Sample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_VERSION = 3.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 05E2127C19D4DB510098F589 /* Build configuration list for PBXProject "Sample" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 05E212A219D4DB510098F589 /* Debug */, + 05E212A319D4DB510098F589 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 5E6D34221DB4C9D000FB9B0A /* Build configuration list for PBXNativeTarget "Sample" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 5E6D34231DB4C9D000FB9B0A /* Debug */, + 5E6D34241DB4C9D000FB9B0A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 05E2127919D4DB510098F589 /* Project object */; +} diff --git a/examples/ASLayoutSpecPlayground-Swift/Sample.xcodeproj/xcshareddata/xcschemes/Sample.xcscheme b/examples/ASLayoutSpecPlayground-Swift/Sample.xcodeproj/xcshareddata/xcschemes/Sample.xcscheme new file mode 100644 index 0000000000..ccd8f696bb --- /dev/null +++ b/examples/ASLayoutSpecPlayground-Swift/Sample.xcodeproj/xcshareddata/xcschemes/Sample.xcscheme @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/ASLayoutSpecPlayground-Swift/Sample/Info.plist b/examples/ASLayoutSpecPlayground-Swift/Sample/Info.plist new file mode 100644 index 0000000000..fbe1e6b314 --- /dev/null +++ b/examples/ASLayoutSpecPlayground-Swift/Sample/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSPrincipalClass + + + diff --git a/examples/ASLayoutSpecPlayground-Swift/Sample/Sample.h b/examples/ASLayoutSpecPlayground-Swift/Sample/Sample.h new file mode 100644 index 0000000000..0c5d69364f --- /dev/null +++ b/examples/ASLayoutSpecPlayground-Swift/Sample/Sample.h @@ -0,0 +1,18 @@ +// +// Sample.h +// Sample +// +// Copyright © 2016 Facebook. All rights reserved. +// + +#import + +//! Project version number for Sample. +FOUNDATION_EXPORT double SampleVersionNumber; + +//! Project version string for Sample. +FOUNDATION_EXPORT const unsigned char SampleVersionString[]; + +// In this header, you should import all the public headers of your framework using statements like #import + + diff --git a/examples/ASLayoutSpecPlayground-Swift/Sample/Sample.playground/Pages/HorizontalStackWithSpacer.xcplaygroundpage/Contents.swift b/examples/ASLayoutSpecPlayground-Swift/Sample/Sample.playground/Pages/HorizontalStackWithSpacer.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000000..10715382bb --- /dev/null +++ b/examples/ASLayoutSpecPlayground-Swift/Sample/Sample.playground/Pages/HorizontalStackWithSpacer.xcplaygroundpage/Contents.swift @@ -0,0 +1,46 @@ +//: [Photo With Outset Icon Overlay](PhotoWithOutsetIconOverlay) + +import AsyncDisplayKit + +extension HorizontalStackWithSpacer { + + override public func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec { + usernameNode.style.flexShrink = 1.0 + postLocationNode.style.flexShrink = 1.0 + + let verticalStackSpec = ASStackLayoutSpec.vertical() + verticalStackSpec.style.flexShrink = 1.0 + + // if fetching post location data from server, check if it is available yet + if postLocationNode.attributedText != nil { + verticalStackSpec.children = [usernameNode, postLocationNode] + } else { + verticalStackSpec.children = [usernameNode] + } + + let spacerSpec = ASLayoutSpec() + spacerSpec.style.flexGrow = 1.0 + spacerSpec.style.flexShrink = 1.0 + + // horizontal stack + let horizontalStack = ASStackLayoutSpec.horizontal() + horizontalStack.alignItems = .center // center items vertically in horiz stack + horizontalStack.justifyContent = .start // justify content to left + horizontalStack.style.flexShrink = 1.0 + horizontalStack.style.flexGrow = 1.0 + horizontalStack.children = [verticalStackSpec, spacerSpec, postTimeNode] + + // inset horizontal stack + let insets = UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 10) + let headerInsetSpec = ASInsetLayoutSpec(insets: insets, child: horizontalStack) + headerInsetSpec.style.flexShrink = 1.0 + headerInsetSpec.style.flexGrow = 1.0 + + return headerInsetSpec + } + +} + +HorizontalStackWithSpacer().show() + +//: [Index](Index) diff --git a/examples/ASLayoutSpecPlayground-Swift/Sample/Sample.playground/Pages/Index.xcplaygroundpage/Contents.swift b/examples/ASLayoutSpecPlayground-Swift/Sample/Sample.playground/Pages/Index.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000000..b44cbd0226 --- /dev/null +++ b/examples/ASLayoutSpecPlayground-Swift/Sample/Sample.playground/Pages/Index.xcplaygroundpage/Contents.swift @@ -0,0 +1,24 @@ +/*: + ## ⚠️ You must start by building the Sample framework ⚠️ + Once that succeeds, you should not have to build until you update AsyncDisplayKit! + What you see here isn't comprehensive, but you should be able to tweak the variables to familiarize yourself with the layout APIs. + - - - + + ## Table of Contents + * [Stack Layout](StackLayout) + * [Photo With Inset Text Overlay](PhotoWithInsetTextOverlay) + * [Photo With Outset Icon Overlay](PhotoWithOutsetIconOverlay) + * [Horizontal Stack With Spacer](HorizontalStackWithSpacer) + + - - - +Tips: + 1. Make sure to show the Assistant Editor in order to preview your code changes. You can do this with either of the following: + - (cmd + opt/alt + ⮐) + - View → Assistant Editor → Show Assistant Editor, to see the preview + 1. Make sure that **Timeline** as the element selected in the Assistant Editor + 1. You might have to click on stop/start (the one at the bottom of the screen, under the editor) a few times in case the timeline isn't updating. + - - - +Solutions to Common Issues: + 1. If you're getting errors regarding **import Sample_Sources**, simply restart Xcode and try again. + 1. If you're getting issues with threading, restart the test until it works. +*/ diff --git a/examples/ASLayoutSpecPlayground-Swift/Sample/Sample.playground/Pages/PhotoWithInsetTextOverlay.xcplaygroundpage/Contents.swift b/examples/ASLayoutSpecPlayground-Swift/Sample/Sample.playground/Pages/PhotoWithInsetTextOverlay.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000000..cc73be4b1a --- /dev/null +++ b/examples/ASLayoutSpecPlayground-Swift/Sample/Sample.playground/Pages/PhotoWithInsetTextOverlay.xcplaygroundpage/Contents.swift @@ -0,0 +1,26 @@ +//: [Stack Layout](StackLayout) + +import AsyncDisplayKit + +let userImageHeight = 60 + +extension PhotoWithInsetTextOverlay { + + override public func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec { + photoNode.style.preferredSize = CGSize(width: userImageHeight * 2, height: userImageHeight * 2) + let backgroundImageAbsoluteSpec = ASAbsoluteLayoutSpec(children: [photoNode]) + + let insets = UIEdgeInsets(top: CGFloat.infinity, left: 12, bottom: 12, right: 12) + let textInsetSpec = ASInsetLayoutSpec(insets: insets, + child: titleNode) + + let textOverlaySpec = ASOverlayLayoutSpec(child: backgroundImageAbsoluteSpec, overlay: textInsetSpec) + + return textOverlaySpec + } + +} + +PhotoWithInsetTextOverlay().show() + +//: [Photo With Outset Icon Overlay](PhotoWithOutsetIconOverlay) \ No newline at end of file diff --git a/examples/ASLayoutSpecPlayground-Swift/Sample/Sample.playground/Pages/PhotoWithOutsetIconOverlay.xcplaygroundpage/Contents.swift b/examples/ASLayoutSpecPlayground-Swift/Sample/Sample.playground/Pages/PhotoWithOutsetIconOverlay.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000000..ab2195f393 --- /dev/null +++ b/examples/ASLayoutSpecPlayground-Swift/Sample/Sample.playground/Pages/PhotoWithOutsetIconOverlay.xcplaygroundpage/Contents.swift @@ -0,0 +1,28 @@ +//: [Photo With Inset Text Overlay](PhotoWithInsetTextOverlay) + +import AsyncDisplayKit + +extension PhotoWithOutsetIconOverlay { + + override public func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec { + let iconWidth: CGFloat = 40 + let iconHeight: CGFloat = 40 + + iconNode.style.preferredSize = CGSize(width: iconWidth, height: iconWidth) + photoNode.style.preferredSize = CGSize(width: 150, height: 150) + + let x: CGFloat = 150 + let y: CGFloat = 0 + + iconNode.style.layoutPosition = CGPoint(x: x, y: y) + photoNode.style.layoutPosition = CGPoint(x: iconWidth * 0.5, y: iconHeight * 0.5); + + let absoluteLayoutSpec = ASAbsoluteLayoutSpec(children: [photoNode, iconNode]) + return absoluteLayoutSpec; + } + +} + +PhotoWithOutsetIconOverlay().show() + +//: [Horizontal Stack With Spacer](HorizontalStackWithSpacer) diff --git a/examples/ASLayoutSpecPlayground-Swift/Sample/Sample.playground/Pages/StackLayout.xcplaygroundpage/Contents.swift b/examples/ASLayoutSpecPlayground-Swift/Sample/Sample.playground/Pages/StackLayout.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000000..d9eb59db8e --- /dev/null +++ b/examples/ASLayoutSpecPlayground-Swift/Sample/Sample.playground/Pages/StackLayout.xcplaygroundpage/Contents.swift @@ -0,0 +1,31 @@ +//: [Index](Index) +/*: + In this example, you can experiment with stack layouts. + */ +import AsyncDisplayKit + +extension StackLayout { + + override public func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec { + // Try commenting out the flexShrink to see its consequences. + subtitleNode.style.flexShrink = 1.0 + + let stackSpec = ASStackLayoutSpec(direction: .horizontal, + spacing: 5, + justifyContent: .start, + alignItems: .start, + children: [titleNode, subtitleNode]) + + let insetSpec = ASInsetLayoutSpec(insets: UIEdgeInsets(top: 5, + left: 5, + bottom: 5, + right: 5), + child: stackSpec) + return insetSpec + } + +} + +StackLayout().show() + +//: [Photo With Inset Text Overlay](PhotoWithInsetTextOverlay) \ No newline at end of file diff --git a/examples/ASLayoutSpecPlayground-Swift/Sample/Sample.playground/Sources/ASPlayground.swift b/examples/ASLayoutSpecPlayground-Swift/Sample/Sample.playground/Sources/ASPlayground.swift new file mode 100644 index 0000000000..0aab532ed3 --- /dev/null +++ b/examples/ASLayoutSpecPlayground-Swift/Sample/Sample.playground/Sources/ASPlayground.swift @@ -0,0 +1,26 @@ +import PlaygroundSupport +import AsyncDisplayKit + +public protocol ASPlayground: class { + func display(inRect: CGRect) +} + +extension ASPlayground { + public func display(inRect rect: CGRect) { + var rect = rect + if rect.size == .zero { + rect.size = CGSize(width: 400, height: 400) + } + + guard let nodeSelf = self as? ASDisplayNode else { + assertionFailure("Class inheriting ASPlayground must be an ASDisplayNode") + return + } + + let constrainedSize = ASSizeRange(min: rect.size, max: rect.size) + _ = ASCalculateRootLayout(nodeSelf, constrainedSize) + nodeSelf.frame = rect + PlaygroundPage.current.needsIndefiniteExecution = true + PlaygroundPage.current.liveView = nodeSelf.view + } +} diff --git a/examples/ASLayoutSpecPlayground-Swift/Sample/Sample.playground/Sources/HorizontalStackWithSpacer.swift b/examples/ASLayoutSpecPlayground-Swift/Sample/Sample.playground/Sources/HorizontalStackWithSpacer.swift new file mode 100644 index 0000000000..03338158fb --- /dev/null +++ b/examples/ASLayoutSpecPlayground-Swift/Sample/Sample.playground/Sources/HorizontalStackWithSpacer.swift @@ -0,0 +1,38 @@ +import AsyncDisplayKit + +fileprivate let fontSize: CGFloat = 20 + +public class HorizontalStackWithSpacer: ASDisplayNode, ASPlayground { + public let usernameNode = ASTextNode() + public let postLocationNode = ASTextNode() + public let postTimeNode = ASTextNode() + + override public init() { + super.init() + backgroundColor = .white + + automaticallyManagesSubnodes = true + setupNodes() + } + + private func setupNodes() { + usernameNode.backgroundColor = .yellow + usernameNode.attributedText = NSAttributedString.attributedString(string: "hannahmbanana", fontSize: fontSize, color: .darkBlueColor(), firstWordColor: nil) + + postLocationNode.backgroundColor = .lightGray + postLocationNode.maximumNumberOfLines = 1; + postLocationNode.attributedText = NSAttributedString.attributedString(string: "San Fransisco, CA", fontSize: fontSize, color: .lightBlueColor(), firstWordColor: nil) + + postTimeNode.backgroundColor = .brown + postTimeNode.attributedText = NSAttributedString.attributedString(string: "30m", fontSize: fontSize, color: .lightGray, firstWordColor: nil) + } + + // This is used to expose this function for overriding in extensions + override public func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec { + return ASLayoutSpec() + } + + public func show() { + display(inRect: CGRect(x: 0, y: 0, width: 450, height: 100)) + } +} diff --git a/examples/ASLayoutSpecPlayground-Swift/Sample/Sample.playground/Sources/PhotoWithInsetTextOverlay.swift b/examples/ASLayoutSpecPlayground-Swift/Sample/Sample.playground/Sources/PhotoWithInsetTextOverlay.swift new file mode 100644 index 0000000000..701d82f834 --- /dev/null +++ b/examples/ASLayoutSpecPlayground-Swift/Sample/Sample.playground/Sources/PhotoWithInsetTextOverlay.swift @@ -0,0 +1,33 @@ +import AsyncDisplayKit + +public class PhotoWithInsetTextOverlay: ASDisplayNode, ASPlayground { + public let photoNode = ASNetworkImageNode() + public let titleNode = ASTextNode() + + override public init() { + super.init() + backgroundColor = .white + + automaticallyManagesSubnodes = true + setupNodes() + } + + private func setupNodes() { + photoNode.url = URL(string: "http://asyncdisplaykit.org/static/images/layout-examples-photo-with-inset-text-overlay-photo.png") + photoNode.backgroundColor = .black + + titleNode.backgroundColor = .blue + titleNode.maximumNumberOfLines = 2 + titleNode.truncationAttributedText = NSAttributedString.attributedString(string: "...", fontSize: 16, color: .white, firstWordColor: nil) + titleNode.attributedText = NSAttributedString.attributedString(string: "family fall hikes", fontSize: 16, color: .white, firstWordColor: nil) + } + + // This is used to expose this function for overriding in extensions + override public func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec { + return ASLayoutSpec() + } + + public func show() { + display(inRect: CGRect(x: 0, y: 0, width: 120, height: 120)) + } +} diff --git a/examples/ASLayoutSpecPlayground-Swift/Sample/Sample.playground/Sources/PhotoWithOutsetIconOverlay.swift b/examples/ASLayoutSpecPlayground-Swift/Sample/Sample.playground/Sources/PhotoWithOutsetIconOverlay.swift new file mode 100644 index 0000000000..469feab7e3 --- /dev/null +++ b/examples/ASLayoutSpecPlayground-Swift/Sample/Sample.playground/Sources/PhotoWithOutsetIconOverlay.swift @@ -0,0 +1,33 @@ +import AsyncDisplayKit + +fileprivate let userImageHeight = 60 + +public class PhotoWithOutsetIconOverlay: ASDisplayNode, ASPlayground { + public let photoNode = ASNetworkImageNode() + public let iconNode = ASNetworkImageNode() + + override public init() { + super.init() + backgroundColor = .white + + automaticallyManagesSubnodes = true + setupNodes() + } + + private func setupNodes() { + photoNode.url = URL(string: "http://asyncdisplaykit.org/static/images/layout-examples-photo-with-outset-icon-overlay-photo.png") + photoNode.backgroundColor = .black + + iconNode.url = URL(string: "http://asyncdisplaykit.org/static/images/layout-examples-photo-with-outset-icon-overlay-icon.png") + iconNode.imageModificationBlock = ASImageNodeRoundBorderModificationBlock(10, .white) + } + + // This is used to expose this function for overriding in extensions + override public func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec { + return ASLayoutSpec() + } + + public func show() { + display(inRect: CGRect(x: 0, y: 0, width: 190, height: 190)) + } +} diff --git a/examples/ASLayoutSpecPlayground-Swift/Sample/Sample.playground/Sources/StackLayout.swift b/examples/ASLayoutSpecPlayground-Swift/Sample/Sample.playground/Sources/StackLayout.swift new file mode 100644 index 0000000000..8eb4b1dbc5 --- /dev/null +++ b/examples/ASLayoutSpecPlayground-Swift/Sample/Sample.playground/Sources/StackLayout.swift @@ -0,0 +1,31 @@ +import AsyncDisplayKit + +public class StackLayout: ASDisplayNode, ASPlayground { + public let titleNode = ASTextNode() + public let subtitleNode = ASTextNode() + + override public init() { + super.init() + backgroundColor = .white + + automaticallyManagesSubnodes = true + setupNodes() + } + + private func setupNodes() { + titleNode.backgroundColor = .blue + titleNode.attributedText = NSAttributedString.attributedString(string: "Headline!", fontSize: 14, color: .white, firstWordColor: nil) + + subtitleNode.backgroundColor = .yellow + subtitleNode.attributedText = NSAttributedString(string: "Lorem ipsum dolor sit amet, sed ex laudem utroque meliore, at cum lucilius vituperata. Ludus mollis consulatu mei eu, esse vocent epicurei sed at. Ut cum recusabo prodesset. Ut cetero periculis sed, mundi senserit est ut. Nam ut sonet mandamus intellegebat, summo voluptaria vim ad.") + } + + // This is used to expose this function for overriding in extensions + override public func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec { + return ASLayoutSpec() + } + + public func show() { + display(inRect: .zero) + } +} diff --git a/examples/ASLayoutSpecPlayground-Swift/Sample/Sample.playground/Sources/Utilities.swift b/examples/ASLayoutSpecPlayground-Swift/Sample/Sample.playground/Sources/Utilities.swift new file mode 100644 index 0000000000..db9a9c2857 --- /dev/null +++ b/examples/ASLayoutSpecPlayground-Swift/Sample/Sample.playground/Sources/Utilities.swift @@ -0,0 +1,43 @@ +import UIKit +import Foundation + +extension UIColor { + + static func darkBlueColor() -> UIColor { + return UIColor(red: 18.0/255.0, green: 86.0/255.0, blue: 136.0/255.0, alpha: 1.0) + } + + + static func lightBlueColor() -> UIColor { + return UIColor(red: 0.0, green: 122.0/255.0, blue: 1.0, alpha: 1.0) + } + + static func duskColor() -> UIColor { + return UIColor(red: 255/255.0, green: 181/255.0, blue: 68/255.0, alpha: 1.0) + } + + static func customOrangeColor() -> UIColor { + return UIColor(red: 40/255.0, green: 43/255.0, blue: 53/255.0, alpha: 1.0) + } + +} + +extension NSAttributedString { + + static func attributedString(string: String, fontSize size: CGFloat, color: UIColor?, firstWordColor: UIColor?) -> NSAttributedString { + let attributes = [NSForegroundColorAttributeName: color ?? UIColor.black, + NSFontAttributeName: UIFont.boldSystemFont(ofSize: size)] + + let attributedString = NSMutableAttributedString(string: string, attributes: attributes) + + if let firstWordColor = firstWordColor { + let nsString = string as NSString + let firstSpaceRange = nsString.rangeOfCharacter(from: NSCharacterSet.whitespaces) + let firstWordRange = NSMakeRange(0, firstSpaceRange.location) + attributedString.addAttribute(NSForegroundColorAttributeName, value: firstWordColor, range: firstWordRange) + } + + return attributedString + } + +} diff --git a/examples/ASLayoutSpecPlayground-Swift/Sample/Sample.playground/contents.xcplayground b/examples/ASLayoutSpecPlayground-Swift/Sample/Sample.playground/contents.xcplayground new file mode 100644 index 0000000000..c7f819f0e3 --- /dev/null +++ b/examples/ASLayoutSpecPlayground-Swift/Sample/Sample.playground/contents.xcplayground @@ -0,0 +1,10 @@ + + + + + + + + + + From fb92b448e06979c4121256de68824f5b2455b48e Mon Sep 17 00:00:00 2001 From: Michael Schneider Date: Fri, 28 Oct 2016 15:39:03 -0700 Subject: [PATCH 56/59] [ASDisplayNode] Proper handling of `constrainedSize` (#2505) * Check in ASLayout if size is valid for sizing instead of valid for layout * Return constrainedSize from calculateSizeThatFits: Remove invalid constrainedSize check within ASNetworkImageNode. Furthermore as ASDisplayNode does not return CGSizeZero anymore we have to give the display nodes we use in tests and are involving a stack spec an intrinsic content size. * Remove extra constrainedSize handling in ASNetworkImageNode handling * Change test to use FLT_MAX --- AsyncDisplayKit/ASDisplayNode.mm | 2 +- AsyncDisplayKit/ASImageNode.mm | 2 +- AsyncDisplayKit/ASNetworkImageNode.mm | 17 ----------------- AsyncDisplayKit/Layout/ASLayout.mm | 2 +- .../ASDisplayNodeImplicitHierarchyTests.m | 17 +++++++++++++++++ AsyncDisplayKitTests/ASDisplayNodeTests.m | 17 +++++++++++++++++ 6 files changed, 37 insertions(+), 20 deletions(-) diff --git a/AsyncDisplayKit/ASDisplayNode.mm b/AsyncDisplayKit/ASDisplayNode.mm index 7b18bc5fd5..a20bbaa9d9 100644 --- a/AsyncDisplayKit/ASDisplayNode.mm +++ b/AsyncDisplayKit/ASDisplayNode.mm @@ -2491,7 +2491,7 @@ void recursivelyTriggerDisplayForLayer(CALayer *layer, BOOL shouldBlock) { __ASDisplayNodeCheckForLayoutMethodOverrides; - return CGSizeZero; + return constrainedSize; } - (id)_layoutElementThatFits:(ASSizeRange)constrainedSize diff --git a/AsyncDisplayKit/ASImageNode.mm b/AsyncDisplayKit/ASImageNode.mm index 1aa0c22587..bdc2180db1 100644 --- a/AsyncDisplayKit/ASImageNode.mm +++ b/AsyncDisplayKit/ASImageNode.mm @@ -190,7 +190,7 @@ struct ASImageNodeDrawParameters { ASDN::MutexLocker l(__instanceLock__); if (_image == nil) { - return constrainedSize; + return [super calculateSizeThatFits:constrainedSize]; } return _image.size; diff --git a/AsyncDisplayKit/ASNetworkImageNode.mm b/AsyncDisplayKit/ASNetworkImageNode.mm index 73ccbebc03..8a989c5c8d 100755 --- a/AsyncDisplayKit/ASNetworkImageNode.mm +++ b/AsyncDisplayKit/ASNetworkImageNode.mm @@ -331,23 +331,6 @@ static const CGSize kMinReleaseImageOnBackgroundSize = {20.0, 20.0}; } } -#pragma mark - Layout and Sizing - -- (CGSize)calculateSizeThatFits:(CGSize)constrainedSize -{ - ASDN::MutexLocker l(__instanceLock__); - - // If the image node is currently in the loading process and no valid size is applied return CGSizeZero for the time - // being. - // TODO: After 2.0 is stable we should remove this behavior as a ASNetworkImageNode is a replaced element and the - // client code should set the size of an image or it's container it's embedded in - if (ASIsCGSizeValidForSize(constrainedSize) == NO && _URL != nil && self.image == nil) { - return CGSizeZero; - } - - return [super calculateSizeThatFits:constrainedSize]; -} - #pragma mark - Private methods, safe to call without lock - (void)handleProgressImage:(UIImage *)progressImage progress:(CGFloat)progress downloadIdentifier:(nullable id)downloadIdentifier diff --git a/AsyncDisplayKit/Layout/ASLayout.mm b/AsyncDisplayKit/Layout/ASLayout.mm index b2f992fe11..b9967f6199 100644 --- a/AsyncDisplayKit/Layout/ASLayout.mm +++ b/AsyncDisplayKit/Layout/ASLayout.mm @@ -72,7 +72,7 @@ static inline NSString * descriptionIndents(NSUInteger indents) // Read this now to avoid @c weak overhead later. _layoutElementType = layoutElement.layoutElementType; - if (!ASIsCGSizeValidForLayout(size)) { + if (!ASIsCGSizeValidForSize(size)) { ASDisplayNodeAssert(NO, @"layoutSize is invalid and unsafe to provide to Core Animation! Release configurations will force to 0, 0. Size = %@, node = %@", NSStringFromCGSize(size), layoutElement); size = CGSizeZero; } else { diff --git a/AsyncDisplayKitTests/ASDisplayNodeImplicitHierarchyTests.m b/AsyncDisplayKitTests/ASDisplayNodeImplicitHierarchyTests.m index 51f8c26ee6..6eac4cd6c0 100644 --- a/AsyncDisplayKitTests/ASDisplayNodeImplicitHierarchyTests.m +++ b/AsyncDisplayKitTests/ASDisplayNodeImplicitHierarchyTests.m @@ -59,11 +59,21 @@ - (void)testInitialNodeInsertionWithOrdering { + static CGSize kSize = {100, 100}; + ASDisplayNode *node1 = [[ASDisplayNode alloc] init]; ASDisplayNode *node2 = [[ASDisplayNode alloc] init]; ASDisplayNode *node3 = [[ASDisplayNode alloc] init]; ASDisplayNode *node4 = [[ASDisplayNode alloc] init]; ASDisplayNode *node5 = [[ASDisplayNode alloc] init]; + + + // As we will involve a stack spec we have to give the nodes an intrinsic content size + node1.style.preferredSize = kSize; + node2.style.preferredSize = kSize; + node3.style.preferredSize = kSize; + node4.style.preferredSize = kSize; + node5.style.preferredSize = kSize; ASSpecTestDisplayNode *node = [[ASSpecTestDisplayNode alloc] init]; node.automaticallyManagesSubnodes = YES; @@ -88,10 +98,17 @@ - (void)testCalculatedLayoutHierarchyTransitions { + static CGSize kSize = {100, 100}; + ASDisplayNode *node1 = [[ASDisplayNode alloc] init]; ASDisplayNode *node2 = [[ASDisplayNode alloc] init]; ASDisplayNode *node3 = [[ASDisplayNode alloc] init]; + // As we will involve a stack spec we have to give the nodes an intrinsic content size + node1.style.preferredSize = kSize; + node2.style.preferredSize = kSize; + node3.style.preferredSize = kSize; + ASSpecTestDisplayNode *node = [[ASSpecTestDisplayNode alloc] init]; node.automaticallyManagesSubnodes = YES; node.layoutSpecBlock = ^(ASDisplayNode *weakNode, ASSizeRange constrainedSize){ diff --git a/AsyncDisplayKitTests/ASDisplayNodeTests.m b/AsyncDisplayKitTests/ASDisplayNodeTests.m index 47fed66bba..a74f324b56 100644 --- a/AsyncDisplayKitTests/ASDisplayNodeTests.m +++ b/AsyncDisplayKitTests/ASDisplayNodeTests.m @@ -2151,4 +2151,21 @@ static bool stringContainsPointer(NSString *description, id p) { XCTAssertThrowsSpecificNamed([node calculateLayoutThatFits:ASSizeRangeMake(CGSizeMake(100, 100))], NSException, NSInternalInconsistencyException); } +- (void)testThatLayoutWithInvalidSizeCausesException +{ + ASDisplayNode *displayNode = [[ASDisplayNode alloc] init]; + ASDisplayNode *node = [[ASDisplayNode alloc] init]; + node.layoutSpecBlock = ^ASLayoutSpec *(ASDisplayNode *node, ASSizeRange constrainedSize) { + return [ASWrapperLayoutSpec wrapperWithLayoutElement:displayNode]; + }; + + XCTAssertThrows([node layoutThatFits:ASSizeRangeMake(CGSizeMake(0, FLT_MAX))]); + + // This dance is necessary as we would assert in case we create an ASDimension that is not real numbers + ASDimension width = displayNode.style.width; + width.value = INFINITY; + displayNode.style.width = width; + XCTAssertThrows([node layoutThatFits:ASSizeRangeMake(CGSizeMake(0, 0), CGSizeMake(INFINITY, INFINITY))]); +} + @end From 09168ceee0fde104adff29d1647ac7ad0fa7293b Mon Sep 17 00:00:00 2001 From: george-gw Date: Sat, 29 Oct 2016 00:40:22 +0200 Subject: [PATCH 57/59] [Swift] Addressed two warnings when building for swift. (#2497) --- AsyncDisplayKit/ASDisplayNode+Deprecated.h | 2 +- AsyncDisplayKit/ASDisplayNode.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/AsyncDisplayKit/ASDisplayNode+Deprecated.h b/AsyncDisplayKit/ASDisplayNode+Deprecated.h index 563766610c..37904690a9 100644 --- a/AsyncDisplayKit/ASDisplayNode+Deprecated.h +++ b/AsyncDisplayKit/ASDisplayNode+Deprecated.h @@ -52,7 +52,7 @@ * * @deprecated Deprecated in version 2.0: Use ASCalculateRootLayout() or ASCalculateLayout() instead */ -- (ASLayout *)measureWithSizeRange:(ASSizeRange)constrainedSize ASDISPLAYNODE_DEPRECATED_MSG("Use layoutThatFits: instead."); +- (nonnull ASLayout *)measureWithSizeRange:(ASSizeRange)constrainedSize ASDISPLAYNODE_DEPRECATED_MSG("Use layoutThatFits: instead."); /** * @abstract Called whenever the visiblity of the node changed. diff --git a/AsyncDisplayKit/ASDisplayNode.h b/AsyncDisplayKit/ASDisplayNode.h index 73639dca9e..3411136147 100644 --- a/AsyncDisplayKit/ASDisplayNode.h +++ b/AsyncDisplayKit/ASDisplayNode.h @@ -814,7 +814,7 @@ extern NSInteger const ASDefaultDrawingPriority; @end -@interface ASDisplayNode (Deprecated) +@interface ASDisplayNode (DeprecatedProtocolMethods) #pragma mark - Deprecated From c4451edab1dd25039dad04939bd2543e861a83b0 Mon Sep 17 00:00:00 2001 From: Michael Schneider Date: Fri, 28 Oct 2016 16:45:22 -0700 Subject: [PATCH 58/59] Add assertion for invalid constrainedSize in calculateSizeThatFits: (#2507) --- AsyncDisplayKit/ASDisplayNode.mm | 2 ++ .../ASDisplayNodeLayoutTests.mm | 25 +++++++++++++++++++ AsyncDisplayKitTests/ASDisplayNodeTests.m | 17 ------------- 3 files changed, 27 insertions(+), 17 deletions(-) diff --git a/AsyncDisplayKit/ASDisplayNode.mm b/AsyncDisplayKit/ASDisplayNode.mm index a20bbaa9d9..85ce357b83 100644 --- a/AsyncDisplayKit/ASDisplayNode.mm +++ b/AsyncDisplayKit/ASDisplayNode.mm @@ -2490,6 +2490,8 @@ void recursivelyTriggerDisplayForLayer(CALayer *layer, BOOL shouldBlock) - (CGSize)calculateSizeThatFits:(CGSize)constrainedSize { __ASDisplayNodeCheckForLayoutMethodOverrides; + + ASDisplayNodeAssert(ASIsCGSizeValidForSize(constrainedSize), @"Cannot calculate size of node because constrained size is infinite and node does not override -calculateSizeThatFits:. Try setting style.preferredSize on the node. Node: %@", self); return constrainedSize; } diff --git a/AsyncDisplayKitTests/ASDisplayNodeLayoutTests.mm b/AsyncDisplayKitTests/ASDisplayNodeLayoutTests.mm index 1862064fc3..161b71cca8 100644 --- a/AsyncDisplayKitTests/ASDisplayNodeLayoutTests.mm +++ b/AsyncDisplayKitTests/ASDisplayNodeLayoutTests.mm @@ -102,4 +102,29 @@ XCTAssertEqual(numberOfLayoutSpecThatFitsCalls, 1, @"Should not remeasure with same bounds"); } +- (void)testThatLayoutWithInvalidSizeCausesException +{ + ASDisplayNode *displayNode = [[ASDisplayNode alloc] init]; + ASDisplayNode *node = [[ASDisplayNode alloc] init]; + node.layoutSpecBlock = ^ASLayoutSpec *(ASDisplayNode *node, ASSizeRange constrainedSize) { + return [ASWrapperLayoutSpec wrapperWithLayoutElement:displayNode]; + }; + + XCTAssertThrows([node layoutThatFits:ASSizeRangeMake(CGSizeMake(0, FLT_MAX))]); + + // This dance is necessary as we would assert in case we create an ASDimension that is not real numbers + ASDimension width = displayNode.style.width; + width.value = INFINITY; + displayNode.style.width = width; + XCTAssertThrows([node layoutThatFits:ASSizeRangeMake(CGSizeMake(0, 0), CGSizeMake(INFINITY, INFINITY))]); +} + +- (void)testThatLayoutCreatedWithInvalidSizeCausesException +{ + ASDisplayNode *displayNode = [[ASDisplayNode alloc] init]; + XCTAssertThrows([ASLayout layoutWithLayoutElement:displayNode size:CGSizeMake(FLT_MAX, FLT_MAX)]); + XCTAssertThrows([ASLayout layoutWithLayoutElement:displayNode size:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX)]); + XCTAssertThrows([ASLayout layoutWithLayoutElement:displayNode size:CGSizeMake(INFINITY, INFINITY)]); +} + @end diff --git a/AsyncDisplayKitTests/ASDisplayNodeTests.m b/AsyncDisplayKitTests/ASDisplayNodeTests.m index a74f324b56..47fed66bba 100644 --- a/AsyncDisplayKitTests/ASDisplayNodeTests.m +++ b/AsyncDisplayKitTests/ASDisplayNodeTests.m @@ -2151,21 +2151,4 @@ static bool stringContainsPointer(NSString *description, id p) { XCTAssertThrowsSpecificNamed([node calculateLayoutThatFits:ASSizeRangeMake(CGSizeMake(100, 100))], NSException, NSInternalInconsistencyException); } -- (void)testThatLayoutWithInvalidSizeCausesException -{ - ASDisplayNode *displayNode = [[ASDisplayNode alloc] init]; - ASDisplayNode *node = [[ASDisplayNode alloc] init]; - node.layoutSpecBlock = ^ASLayoutSpec *(ASDisplayNode *node, ASSizeRange constrainedSize) { - return [ASWrapperLayoutSpec wrapperWithLayoutElement:displayNode]; - }; - - XCTAssertThrows([node layoutThatFits:ASSizeRangeMake(CGSizeMake(0, FLT_MAX))]); - - // This dance is necessary as we would assert in case we create an ASDimension that is not real numbers - ASDimension width = displayNode.style.width; - width.value = INFINITY; - displayNode.style.width = width; - XCTAssertThrows([node layoutThatFits:ASSizeRangeMake(CGSizeMake(0, 0), CGSizeMake(INFINITY, INFINITY))]); -} - @end From d83f058f821792fe403002a878f586cc37366ac7 Mon Sep 17 00:00:00 2001 From: george-gw Date: Sat, 29 Oct 2016 18:50:11 +0200 Subject: [PATCH 59/59] Deprecate indexPath-based Methods on ASTableView/ASCollectionView (#2498) * Deprecated indexPath methods in ASTableView and ASTableNode and added several indexPath methods to ASTableNode and ASCollectionNode. * Fixed incorrect doc. Removed unnecessary __kindof. --- AsyncDisplayKit/ASCollectionNode.h | 18 ++++ AsyncDisplayKit/ASCollectionNode.mm | 58 +++++++++--- AsyncDisplayKit/ASCollectionView.h | 2 + AsyncDisplayKit/ASCollectionView.mm | 22 ----- AsyncDisplayKit/ASTableNode.h | 69 ++++++++++++++- AsyncDisplayKit/ASTableNode.mm | 88 +++++++++++++++++-- AsyncDisplayKit/ASTableView.h | 2 + AsyncDisplayKit/ASTableView.mm | 39 ++++---- AsyncDisplayKit/ASTableViewInternal.h | 14 +++ .../Details/ASCollectionInternal.h | 7 ++ 10 files changed, 257 insertions(+), 62 deletions(-) diff --git a/AsyncDisplayKit/ASCollectionNode.h b/AsyncDisplayKit/ASCollectionNode.h index bb3dfae87b..1c29a4b580 100644 --- a/AsyncDisplayKit/ASCollectionNode.h +++ b/AsyncDisplayKit/ASCollectionNode.h @@ -375,6 +375,24 @@ NS_ASSUME_NONNULL_BEGIN */ - (NSArray<__kindof NSIndexPath *> *)indexPathsForVisibleItems AS_WARN_UNUSED_RESULT; +/** + * Retrieve the index path of the item at the given point. + * + * @param point The point of the requested item. + * + * @return The indexPath for the item at the given point. This must be called on the main thread. + */ +- (nullable NSIndexPath *)indexPathForItemAtPoint:(CGPoint)point AS_WARN_UNUSED_RESULT; + +/** + * Retrieve the cell at the given index path. + * + * @param indexPath The index path of the requested item. + * + * @return The cell for the given index path. This must be called on the main thread. + */ +- (nullable UICollectionViewCell *)cellForItemAtIndexPath:(NSIndexPath *)indexPath; + /** * Retrieves the context object for the given section, as provided by the data source in * the @c collectionNode:contextForSection: method. diff --git a/AsyncDisplayKit/ASCollectionNode.mm b/AsyncDisplayKit/ASCollectionNode.mm index a073769b08..4525e590fa 100644 --- a/AsyncDisplayKit/ASCollectionNode.mm +++ b/AsyncDisplayKit/ASCollectionNode.mm @@ -322,17 +322,29 @@ - (void)selectItemAtIndexPath:(nullable NSIndexPath *)indexPath animated:(BOOL)animated scrollPosition:(UICollectionViewScrollPosition)scrollPosition { ASDisplayNodeAssertMainThread(); - // TODO: Solve this in a way to be able to remove this restriction (https://github.com/facebook/AsyncDisplayKit/pull/2453#discussion_r84515457) - ASDisplayNodeAssert([self isNodeLoaded], @"ASCollectionNode should be loaded before calling selectItemAtIndexPath"); - [self.view selectItemAtIndexPath:indexPath animated:animated scrollPosition:scrollPosition]; + ASCollectionView *collectionView = self.view; + + indexPath = [collectionView convertIndexPathFromCollectionNode:indexPath waitingIfNeeded:YES]; + + if (indexPath != nil) { + [collectionView selectItemAtIndexPath:indexPath animated:animated scrollPosition:scrollPosition]; + } else { + NSLog(@"Failed to select item at index path %@ because the item never reached the view.", indexPath); + } } - (void)deselectItemAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated { ASDisplayNodeAssertMainThread(); - // TODO: Solve this in a way to be able to remove this restriction (https://github.com/facebook/AsyncDisplayKit/pull/2453#discussion_r84515457) - ASDisplayNodeAssert([self isNodeLoaded], @"ASCollectionNode should be loaded before calling deselectItemAtIndexPath"); - [self.view deselectItemAtIndexPath:indexPath animated:animated]; + ASCollectionView *collectionView = self.view; + + indexPath = [collectionView convertIndexPathFromCollectionNode:indexPath waitingIfNeeded:YES]; + + if (indexPath != nil) { + [collectionView deselectItemAtIndexPath:indexPath animated:animated]; + } else { + NSLog(@"Failed to deselect item at index path %@ because the item never reached the view.", indexPath); + } } - (void)scrollToItemAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UICollectionViewScrollPosition)scrollPosition animated:(BOOL)animated @@ -376,13 +388,20 @@ return self.isNodeLoaded ? [self.view visibleNodes] : @[]; } +- (ASCellNode *)nodeForItemAtIndexPath:(NSIndexPath *)indexPath +{ + [self reloadDataInitiallyIfNeeded]; + return [self.dataController nodeAtIndexPath:indexPath]; +} + - (NSIndexPath *)indexPathForNode:(ASCellNode *)cellNode { return [self.dataController indexPathForNode:cellNode]; } -- (NSArray<__kindof NSIndexPath *> *)indexPathsForVisibleItems +- (NSArray *)indexPathsForVisibleItems { + ASDisplayNodeAssertMainThread(); NSMutableArray *indexPathsArray = [NSMutableArray new]; for (ASCellNode *cell in [self visibleNodes]) { NSIndexPath *indexPath = [self indexPathForNode:cell]; @@ -393,11 +412,28 @@ return indexPathsArray; } - -- (ASCellNode *)nodeForItemAtIndexPath:(NSIndexPath *)indexPath +- (nullable NSIndexPath *)indexPathForItemAtPoint:(CGPoint)point { - [self reloadDataInitiallyIfNeeded]; - return [self.dataController nodeAtIndexPath:indexPath]; + ASDisplayNodeAssertMainThread(); + ASCollectionView *collectionView = self.view; + + NSIndexPath *indexPath = [collectionView indexPathForItemAtPoint:point]; + if (indexPath != nil) { + return [collectionView convertIndexPathToCollectionNode:indexPath]; + } + return indexPath; +} + +- (nullable UICollectionViewCell *)cellForItemAtIndexPath:(NSIndexPath *)indexPath +{ + ASDisplayNodeAssertMainThread(); + ASCollectionView *collectionView = self.view; + + indexPath = [collectionView convertIndexPathFromCollectionNode:indexPath waitingIfNeeded:YES]; + if (indexPath == nil) { + return nil; + } + return [collectionView cellForItemAtIndexPath:indexPath]; } - (id)contextForSection:(NSInteger)section diff --git a/AsyncDisplayKit/ASCollectionView.h b/AsyncDisplayKit/ASCollectionView.h index 33806b4c00..b6c0b73e5f 100644 --- a/AsyncDisplayKit/ASCollectionView.h +++ b/AsyncDisplayKit/ASCollectionView.h @@ -214,6 +214,8 @@ NS_ASSUME_NONNULL_BEGIN */ - (void)scrollToItemAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UICollectionViewScrollPosition)scrollPosition animated:(BOOL)animated ASDISPLAYNODE_DEPRECATED_MSG("Use ASCollectionNode method instead."); +- (void)selectItemAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated scrollPosition:(UICollectionViewScrollPosition)scrollPosition ASDISPLAYNODE_DEPRECATED_MSG("Use ASCollectionNode method instead."); + /** * Perform a batch of updates asynchronously, optionally disabling all animations in the batch. This method must be called from the main thread. * The asyncDataSource must be updated to reflect the changes before the update block completes. diff --git a/AsyncDisplayKit/ASCollectionView.mm b/AsyncDisplayKit/ASCollectionView.mm index 06aab6899b..969402d7ce 100644 --- a/AsyncDisplayKit/ASCollectionView.mm +++ b/AsyncDisplayKit/ASCollectionView.mm @@ -608,28 +608,6 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell"; return visibleNodes; } -/** - * TODO: This method was built when the distinction between data source - * index paths and view index paths was unclear. For compatibility, it - * still expects data source index paths for the time being. - */ -- (void)selectItemAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated scrollPosition:(UICollectionViewScrollPosition)scrollPosition -{ - ASDisplayNodeAssertMainThread(); - // If they passed nil, just forward it and be done. - if (indexPath == nil) { - [super selectItemAtIndexPath:indexPath animated:animated scrollPosition:scrollPosition]; - return; - } - - NSIndexPath *viewIndexPath = [self convertIndexPathFromCollectionNode:indexPath waitingIfNeeded:YES]; - if (viewIndexPath != nil) { - [super selectItemAtIndexPath:viewIndexPath animated:animated scrollPosition:scrollPosition]; - } else { - NSLog(@"Warning: Ignoring request to select item at index path %@ because the item did not reach the collection view.", indexPath); - } -} - #pragma mark Internal /** diff --git a/AsyncDisplayKit/ASTableNode.h b/AsyncDisplayKit/ASTableNode.h index 83ae540cc7..e656f1b083 100644 --- a/AsyncDisplayKit/ASTableNode.h +++ b/AsyncDisplayKit/ASTableNode.h @@ -291,7 +291,6 @@ NS_ASSUME_NONNULL_BEGIN */ - (void)deselectRowAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated; - #pragma mark - Querying Data /** @@ -327,6 +326,74 @@ NS_ASSUME_NONNULL_BEGIN */ - (nullable NSIndexPath *)indexPathForNode:(ASCellNode *)cellNode AS_WARN_UNUSED_RESULT; +/** + * Similar to -[UITableView rectForRowAtIndexPath:] + * + * @param indexPath An index path identifying a row in the table view. + * + * @return A rectangle defining the area in which the table view draws the row or CGRectZero if indexPath is invalid. + * + * @discussion This method must be called from the main thread. + */ +- (CGRect)rectForRowAtIndexPath:(NSIndexPath *)indexPath AS_WARN_UNUSED_RESULT; + +/** + * Similar to -[UITableView cellForRowAtIndexPath:] + * + * @param indexPath An index path identifying a row in the table view. + * + * @return An object representing a cell of the table, or nil if the cell is not visible or indexPath is out of range. + * + * @discussion This method must be called from the main thread. + */ +- (nullable __kindof UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath *)indexPath AS_WARN_UNUSED_RESULT; + +/** + * Similar to -[UITableView indexPathForSelectedRow] + * + * @return The value of this property is an index path identifying the row and section + * indexes of the selected row, or nil if the index path is invalid. If there are multiple selections, + * this property contains the first index-path object in the array of row selections; + * this object has the lowest index values for section and row. + * + * @discussion This method must be called from the main thread. + */ +- (nullable NSIndexPath *)indexPathForSelectedRow AS_WARN_UNUSED_RESULT; + +/** + * Similar to -[UITableView indexPathForRowAtPoint:] + * + * @param point A point in the local coordinate system of the table view (the table view’€™s bounds). + * + * @return An index path representing the row and section associated with point, + * or nil if the point is out of the bounds of any row. + * + * @discussion This method must be called from the main thread. + */ +- (nullable NSIndexPath *)indexPathForRowAtPoint:(CGPoint)point AS_WARN_UNUSED_RESULT; + +/** + * Similar to -[UITableView indexPathsForRowsInRect:] + * + * @param rect A rectangle defining an area of the table view in local coordinates. + * + * @return An array of NSIndexPath objects each representing a row and section index identifying a row within rect. + * Returns an empty array if there aren’t any rows to return. + * + * @discussion This method must be called from the main thread. + */ +- (nullable NSArray *)indexPathsForRowsInRect:(CGRect)rect AS_WARN_UNUSED_RESULT; + +/** + * Similar to -[UITableView indexPathsForVisibleRows] + * + * @return The value of this property is an array of NSIndexPath objects each representing a row index and section index + * that together identify a visible row in the table view. If no rows are visible, the value is nil. + * + * @discussion This method must be called from the main thread. + */ +- (NSArray *)indexPathsForVisibleRows AS_WARN_UNUSED_RESULT; + @end /** diff --git a/AsyncDisplayKit/ASTableNode.mm b/AsyncDisplayKit/ASTableNode.mm index 954a2ae26e..6fd58035a7 100644 --- a/AsyncDisplayKit/ASTableNode.mm +++ b/AsyncDisplayKit/ASTableNode.mm @@ -346,17 +346,28 @@ ASEnvironmentCollectionTableSetEnvironmentState(_environmentStateLock) - (void)selectRowAtIndexPath:(nullable NSIndexPath *)indexPath animated:(BOOL)animated scrollPosition:(UITableViewScrollPosition)scrollPosition { ASDisplayNodeAssertMainThread(); - // TODO: Solve this in a way to be able to remove this restriction (https://github.com/facebook/AsyncDisplayKit/pull/2453#discussion_r84515457) - ASDisplayNodeAssert([self isNodeLoaded], @"ASTableNode should be loaded before calling selectRowAtIndexPath"); - [self.view selectRowAtIndexPath:indexPath animated:animated scrollPosition:scrollPosition]; + ASTableView *tableView = self.view; + + indexPath = [tableView convertIndexPathFromTableNode:indexPath waitingIfNeeded:YES]; + if (indexPath != nil) { + [tableView selectRowAtIndexPath:indexPath animated:animated scrollPosition:scrollPosition]; + } else { + NSLog(@"Failed to select row at index path %@ because the row never reached the view.", indexPath); + } + } - (void)deselectRowAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated { ASDisplayNodeAssertMainThread(); - // TODO: Solve this in a way to be able to remove this restriction (https://github.com/facebook/AsyncDisplayKit/pull/2453#discussion_r84515457) - ASDisplayNodeAssert([self isNodeLoaded], @"ASTableNode should be loaded before calling deselectRowAtIndexPath"); - [self.view deselectRowAtIndexPath:indexPath animated:animated]; + ASTableView *tableView = self.view; + + indexPath = [tableView convertIndexPathFromTableNode:indexPath waitingIfNeeded:YES]; + if (indexPath != nil) { + [tableView deselectRowAtIndexPath:indexPath animated:animated]; + } else { + NSLog(@"Failed to deselect row at index path %@ because the row never reached the view.", indexPath); + } } - (void)scrollToRowAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UITableViewScrollPosition)scrollPosition animated:(BOOL)animated @@ -411,6 +422,71 @@ ASEnvironmentCollectionTableSetEnvironmentState(_environmentStateLock) return [self.dataController nodeAtIndexPath:indexPath]; } +- (CGRect)rectForRowAtIndexPath:(NSIndexPath *)indexPath +{ + ASDisplayNodeAssertMainThread(); + ASTableView *tableView = self.view; + + indexPath = [tableView convertIndexPathFromTableNode:indexPath waitingIfNeeded:YES]; + return [tableView rectForRowAtIndexPath:indexPath]; +} + +- (nullable __kindof UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath *)indexPath +{ + ASDisplayNodeAssertMainThread(); + ASTableView *tableView = self.view; + + indexPath = [tableView convertIndexPathFromTableNode:indexPath waitingIfNeeded:YES]; + if (indexPath == nil) { + return nil; + } + return [tableView cellForRowAtIndexPath:indexPath]; +} + +- (nullable NSIndexPath *)indexPathForSelectedRow +{ + ASDisplayNodeAssertMainThread(); + ASTableView *tableView = self.view; + + NSIndexPath *indexPath = tableView.indexPathForSelectedRow; + if (indexPath != nil) { + return [tableView convertIndexPathToTableNode:indexPath]; + } + return indexPath; +} + +- (nullable NSIndexPath *)indexPathForRowAtPoint:(CGPoint)point +{ + ASDisplayNodeAssertMainThread(); + ASTableView *tableView = self.view; + + NSIndexPath *indexPath = [tableView indexPathForRowAtPoint:point]; + if (indexPath != nil) { + return [tableView convertIndexPathToTableNode:indexPath]; + } + return indexPath; +} + +- (nullable NSArray *)indexPathsForRowsInRect:(CGRect)rect +{ + ASDisplayNodeAssertMainThread(); + ASTableView *tableView = self.view; + return [tableView convertIndexPathsToTableNode:[tableView indexPathsForRowsInRect:rect]]; +} + +- (NSArray *)indexPathsForVisibleRows +{ + ASDisplayNodeAssertMainThread(); + NSMutableArray *indexPathsArray = [NSMutableArray new]; + for (ASCellNode *cell in [self visibleNodes]) { + NSIndexPath *indexPath = [self indexPathForNode:cell]; + if (indexPath) { + [indexPathsArray addObject:indexPath]; + } + } + return indexPathsArray; +} + #pragma mark - Editing - (void)reloadDataWithCompletion:(void (^)())completion diff --git a/AsyncDisplayKit/ASTableView.h b/AsyncDisplayKit/ASTableView.h index 2bed257651..b454e497ed 100644 --- a/AsyncDisplayKit/ASTableView.h +++ b/AsyncDisplayKit/ASTableView.h @@ -133,6 +133,8 @@ NS_ASSUME_NONNULL_BEGIN */ - (void)scrollToRowAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UITableViewScrollPosition)scrollPosition animated:(BOOL)animated ASDISPLAYNODE_DEPRECATED_MSG("Use ASTableNode method instead."); +- (void)selectRowAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated scrollPosition:(UITableViewScrollPosition)scrollPosition; ASDISPLAYNODE_DEPRECATED_MSG("Use ASTableNode method instead."); + /** * Similar to -visibleCells. * diff --git a/AsyncDisplayKit/ASTableView.mm b/AsyncDisplayKit/ASTableView.mm index e51a92cec1..8a3334eac5 100644 --- a/AsyncDisplayKit/ASTableView.mm +++ b/AsyncDisplayKit/ASTableView.mm @@ -486,6 +486,23 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell"; } } +- (NSArray *)convertIndexPathsToTableNode:(NSArray *)indexPaths +{ + if (indexPaths == nil) { + return nil; + } + + NSMutableArray *indexPathsArray = [NSMutableArray new]; + + for (NSIndexPath *indexPathInView in indexPaths) { + NSIndexPath *indexPath = [self convertIndexPathToTableNode:indexPathInView]; + if (indexPath != nil) { + [indexPathsArray addObject:indexPath]; + } + } + return indexPathsArray; +} + - (NSIndexPath *)indexPathForNode:(ASCellNode *)cellNode { return [self indexPathForNode:cellNode waitingIfNeeded:NO]; @@ -540,28 +557,6 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell"; [_dataController waitUntilAllUpdatesAreCommitted]; } -/** - * TODO: This method was built when the distinction between data source - * index paths and view index paths was unclear. For compatibility, it - * still expects data source index paths for the time being. - */ -- (void)selectRowAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated scrollPosition:(UITableViewScrollPosition)scrollPosition -{ - ASDisplayNodeAssertMainThread(); - // If they passed nil, just forward it and be done. - if (indexPath == nil) { - [super selectRowAtIndexPath:indexPath animated:animated scrollPosition:scrollPosition]; - return; - } - - indexPath = [self convertIndexPathFromTableNode:indexPath waitingIfNeeded:YES]; - if (indexPath != nil) { - [super selectRowAtIndexPath:indexPath animated:YES scrollPosition:scrollPosition]; - } else { - NSLog(@"Warning: Ignoring request to select row at index path %@ because the item did not reach the table view.", indexPath); - } -} - - (void)layoutSubviews { if (_nodesConstrainedWidth != self.bounds.size.width) { diff --git a/AsyncDisplayKit/ASTableViewInternal.h b/AsyncDisplayKit/ASTableViewInternal.h index 0a9cbf63aa..8b36014a52 100644 --- a/AsyncDisplayKit/ASTableViewInternal.h +++ b/AsyncDisplayKit/ASTableViewInternal.h @@ -45,4 +45,18 @@ */ - (NSIndexPath *)convertIndexPathFromTableNode:(NSIndexPath *)indexPath waitingIfNeeded:(BOOL)wait; +/** + * Attempt to get the node index path given the view-layer index path. + * + * @param indexPath The index path of the row. + */ +- (NSIndexPath *)convertIndexPathToTableNode:(NSIndexPath *)indexPath; + +/** + * Attempt to get the node index paths given the view-layer index paths. + * + * @param indexPaths An array of index paths in the view space + */ +- (NSArray *)convertIndexPathsToTableNode:(NSArray *)indexPaths; + @end diff --git a/AsyncDisplayKit/Details/ASCollectionInternal.h b/AsyncDisplayKit/Details/ASCollectionInternal.h index 1b4e7cc7a3..c17c8d689a 100644 --- a/AsyncDisplayKit/Details/ASCollectionInternal.h +++ b/AsyncDisplayKit/Details/ASCollectionInternal.h @@ -34,6 +34,13 @@ NS_ASSUME_NONNULL_BEGIN */ - (nullable NSIndexPath *)convertIndexPathFromCollectionNode:(NSIndexPath *)indexPath waitingIfNeeded:(BOOL)wait; +/** + * Attempt to get the node index path given the view-layer index path. + * + * @param indexPath The index path of the row. + */ +- (NSIndexPath *)convertIndexPathToCollectionNode:(NSIndexPath *)indexPath; + @end NS_ASSUME_NONNULL_END