From 2e331656cfbf106817e6b9d6b6017b88a044caa4 Mon Sep 17 00:00:00 2001 From: Scott Goodson Date: Sat, 31 Oct 2015 16:40:26 -0700 Subject: [PATCH 1/9] Add "Push Another Copy" to ASViewController demo for memory testing. So far unable to reproduce the reports of rows or items not being released. --- .../ASCollectionView/Sample/AppDelegate.m | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/examples/ASCollectionView/Sample/AppDelegate.m b/examples/ASCollectionView/Sample/AppDelegate.m index 95c8b2da5c..a979170a63 100644 --- a/examples/ASCollectionView/Sample/AppDelegate.m +++ b/examples/ASCollectionView/Sample/AppDelegate.m @@ -15,12 +15,32 @@ @implementation AppDelegate -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions +{ self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; self.window.backgroundColor = [UIColor whiteColor]; - self.window.rootViewController = [[ViewController alloc] init]; + self.window.rootViewController = [[UINavigationController alloc] init]; + + [self pushNewViewControllerAnimated:NO]; + [self.window makeKeyAndVisible]; + return YES; } +- (void)pushNewViewControllerAnimated:(BOOL)animated +{ + UINavigationController *navController = (UINavigationController *)self.window.rootViewController; + + UIViewController *viewController = [[ViewController alloc] init]; + viewController.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Push Another Copy" style:UIBarButtonItemStylePlain target:self action:@selector(pushNewViewController)]; + + [navController pushViewController:viewController animated:animated]; +} + +- (void)pushNewViewController +{ + [self pushNewViewControllerAnimated:YES]; +} + @end From 59c1a642ba36709b0882137668f591d45d28041a Mon Sep 17 00:00:00 2001 From: Scott Goodson Date: Sat, 31 Oct 2015 16:53:56 -0700 Subject: [PATCH 2/9] Add reload button to ASViewController demo for memory testing. --- examples/ASCollectionView/Sample/ViewController.m | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/examples/ASCollectionView/Sample/ViewController.m b/examples/ASCollectionView/Sample/ViewController.m index 01350da1a3..4f337ce1d1 100644 --- a/examples/ASCollectionView/Sample/ViewController.m +++ b/examples/ASCollectionView/Sample/ViewController.m @@ -44,6 +44,9 @@ [_collectionView registerSupplementaryNodeOfKind:UICollectionElementKindSectionHeader]; [_collectionView registerSupplementaryNodeOfKind:UICollectionElementKindSectionFooter]; + self.navigationItem.leftItemsSupplementBackButton = YES; + self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh target:self action:@selector(reloadTapped)]; + return self; } @@ -64,6 +67,10 @@ return YES; } +- (void)reloadTapped +{ + [_collectionView reloadData]; +} #pragma mark - #pragma mark ASCollectionView data source. From fdcace606152ae60bba0290cf455ed6d4f4aa273 Mon Sep 17 00:00:00 2001 From: Scott Goodson Date: Sun, 1 Nov 2015 10:54:11 -0800 Subject: [PATCH 3/9] Add multiple view push to the ASTableViewStressTest app to evaluate memory issues No issues found. Have not been able to create a leak either with the test itself or scrolling / popping back view controlliers. --- .../Sample.xcodeproj/project.pbxproj | 20 ++++++++++++++-- .../Sample.xcodeproj/project.pbxproj | 16 +++++++++++++ .../Sample/AppDelegate.m | 23 +++++++++++++++++-- .../Sample/ViewController.m | 2 +- 4 files changed, 56 insertions(+), 5 deletions(-) diff --git a/examples/ASCollectionView/Sample.xcodeproj/project.pbxproj b/examples/ASCollectionView/Sample.xcodeproj/project.pbxproj index 959990a70e..9e3d98c2b5 100644 --- a/examples/ASCollectionView/Sample.xcodeproj/project.pbxproj +++ b/examples/ASCollectionView/Sample.xcodeproj/project.pbxproj @@ -7,8 +7,8 @@ objects = { /* Begin PBXBuildFile section */ - 9B92C8811BC17D3000EE46B2 /* SupplementaryNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B92C8801BC17D3000EE46B2 /* SupplementaryNode.m */; settings = {ASSET_TAGS = (); }; }; - 9BA2CEA11BB2579C00D18414 /* Launchboard.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9BA2CEA01BB2579C00D18414 /* Launchboard.storyboard */; settings = {ASSET_TAGS = (); }; }; + 9B92C8811BC17D3000EE46B2 /* SupplementaryNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B92C8801BC17D3000EE46B2 /* SupplementaryNode.m */; }; + 9BA2CEA11BB2579C00D18414 /* Launchboard.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9BA2CEA01BB2579C00D18414 /* Launchboard.storyboard */; }; AC3C4A641A11F47200143C57 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = AC3C4A631A11F47200143C57 /* main.m */; }; AC3C4A671A11F47200143C57 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = AC3C4A661A11F47200143C57 /* AppDelegate.m */; }; AC3C4A6A1A11F47200143C57 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = AC3C4A691A11F47200143C57 /* ViewController.m */; }; @@ -120,6 +120,7 @@ AC3C4A5B1A11F47200143C57 /* Frameworks */, AC3C4A5C1A11F47200143C57 /* Resources */, A6902C454C7661D0D277AC62 /* Copy Pods Resources */, + EC37EEC9933F5786936BFE7C /* Embed Pods Frameworks */, ); buildRules = ( ); @@ -190,6 +191,21 @@ shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-resources.sh\"\n"; showEnvVarsInLog = 0; }; + EC37EEC9933F5786936BFE7C /* Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Embed Pods Frameworks"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; F868CFBB21824CC9521B6588 /* Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; diff --git a/examples/ASTableViewStressTest/Sample.xcodeproj/project.pbxproj b/examples/ASTableViewStressTest/Sample.xcodeproj/project.pbxproj index e066c2fcd1..30be626c5c 100644 --- a/examples/ASTableViewStressTest/Sample.xcodeproj/project.pbxproj +++ b/examples/ASTableViewStressTest/Sample.xcodeproj/project.pbxproj @@ -118,6 +118,7 @@ 05E2127E19D4DB510098F589 /* Frameworks */, 05E2127F19D4DB510098F589 /* Resources */, F012A6F39E0149F18F564F50 /* Copy Pods Resources */, + E671F9E92DFB9088485E493B /* Embed Pods Frameworks */, ); buildRules = ( ); @@ -189,6 +190,21 @@ shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; showEnvVarsInLog = 0; }; + E671F9E92DFB9088485E493B /* Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Embed Pods Frameworks"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; F012A6F39E0149F18F564F50 /* Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; diff --git a/examples/ASTableViewStressTest/Sample/AppDelegate.m b/examples/ASTableViewStressTest/Sample/AppDelegate.m index a8e5594780..a8d611608c 100644 --- a/examples/ASTableViewStressTest/Sample/AppDelegate.m +++ b/examples/ASTableViewStressTest/Sample/AppDelegate.m @@ -19,9 +19,28 @@ { self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; self.window.backgroundColor = [UIColor whiteColor]; - self.window.rootViewController = [[ViewController alloc] init]; + self.window.rootViewController = [[UINavigationController alloc] init]; + + [self pushNewViewControllerAnimated:NO]; + [self.window makeKeyAndVisible]; + return YES; } -@end +- (void)pushNewViewControllerAnimated:(BOOL)animated +{ + UINavigationController *navController = (UINavigationController *)self.window.rootViewController; + + UIViewController *viewController = [[ViewController alloc] init]; + viewController.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Push Another Copy" style:UIBarButtonItemStylePlain target:self action:@selector(pushNewViewController)]; + + [navController pushViewController:viewController animated:animated]; +} + +- (void)pushNewViewController +{ + [self pushNewViewControllerAnimated:YES]; +} + +@end \ No newline at end of file diff --git a/examples/ASTableViewStressTest/Sample/ViewController.m b/examples/ASTableViewStressTest/Sample/ViewController.m index f082e565f0..4133c1741d 100644 --- a/examples/ASTableViewStressTest/Sample/ViewController.m +++ b/examples/ASTableViewStressTest/Sample/ViewController.m @@ -16,7 +16,7 @@ #define NumberOfSections 10 #define NumberOfRowsPerSection 20 -#define NumberOfReloadIterations 500 +#define NumberOfReloadIterations 50 @interface ViewController () { From 3018030c00f0913834f33418b21f076794811419 Mon Sep 17 00:00:00 2001 From: Steven Ramkumar Date: Wed, 4 Nov 2015 17:52:16 -0800 Subject: [PATCH 4/9] Add a ASTableNode class, similar to ASCollectionNode --- AsyncDisplayKit.xcodeproj/project.pbxproj | 8 +++++++ AsyncDisplayKit/ASTableNode.h | 21 +++++++++++++++++ AsyncDisplayKit/ASTableNode.m | 28 +++++++++++++++++++++++ 3 files changed, 57 insertions(+) create mode 100644 AsyncDisplayKit/ASTableNode.h create mode 100644 AsyncDisplayKit/ASTableNode.m diff --git a/AsyncDisplayKit.xcodeproj/project.pbxproj b/AsyncDisplayKit.xcodeproj/project.pbxproj index 2b412a4527..cfb767f482 100644 --- a/AsyncDisplayKit.xcodeproj/project.pbxproj +++ b/AsyncDisplayKit.xcodeproj/project.pbxproj @@ -293,6 +293,8 @@ ACF6ED611B178DC700DA7C62 /* ASOverlayLayoutSpecSnapshotTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = ACF6ED591B178DC700DA7C62 /* ASOverlayLayoutSpecSnapshotTests.mm */; }; ACF6ED621B178DC700DA7C62 /* ASRatioLayoutSpecSnapshotTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = ACF6ED5A1B178DC700DA7C62 /* ASRatioLayoutSpecSnapshotTests.mm */; }; ACF6ED631B178DC700DA7C62 /* ASStackLayoutSpecSnapshotTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = ACF6ED5B1B178DC700DA7C62 /* ASStackLayoutSpecSnapshotTests.mm */; }; + B0F8805A1BEAEC7500D17647 /* ASTableNode.h in Headers */ = {isa = PBXBuildFile; fileRef = B0F880581BEAEC7500D17647 /* ASTableNode.h */; }; + B0F8805B1BEAEC7500D17647 /* ASTableNode.m in Sources */ = {isa = PBXBuildFile; fileRef = B0F880591BEAEC7500D17647 /* ASTableNode.m */; }; B35061F31B010EFD0018CF92 /* ASCellNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 055F1A3A19ABD43F004DAFF1 /* ASCellNode.h */; settings = {ATTRIBUTES = (Public, ); }; }; B35061F51B010EFD0018CF92 /* ASCollectionView.h in Headers */ = {isa = PBXBuildFile; fileRef = AC3C4A4F1A1139C100143C57 /* ASCollectionView.h */; settings = {ATTRIBUTES = (Public, ); }; }; B35061F61B010EFD0018CF92 /* ASCollectionView.mm in Sources */ = {isa = PBXBuildFile; fileRef = AC3C4A501A1139C100143C57 /* ASCollectionView.mm */; }; @@ -661,6 +663,8 @@ ACF6ED591B178DC700DA7C62 /* ASOverlayLayoutSpecSnapshotTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASOverlayLayoutSpecSnapshotTests.mm; sourceTree = ""; }; ACF6ED5A1B178DC700DA7C62 /* ASRatioLayoutSpecSnapshotTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASRatioLayoutSpecSnapshotTests.mm; sourceTree = ""; }; ACF6ED5B1B178DC700DA7C62 /* ASStackLayoutSpecSnapshotTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASStackLayoutSpecSnapshotTests.mm; sourceTree = ""; }; + B0F880581BEAEC7500D17647 /* ASTableNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASTableNode.h; sourceTree = ""; }; + B0F880591BEAEC7500D17647 /* ASTableNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASTableNode.m; sourceTree = ""; }; B35061DA1B010EDF0018CF92 /* AsyncDisplayKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = AsyncDisplayKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; B35061DD1B010EDF0018CF92 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = "../AsyncDisplayKit-iOS/Info.plist"; sourceTree = ""; }; CC7FD9DC1BB5E962005CCB2B /* ASPhotosFrameworkImageRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASPhotosFrameworkImageRequest.h; sourceTree = ""; }; @@ -810,6 +814,8 @@ 055B9FA71A1C154B00035D6D /* ASNetworkImageNode.mm */, D785F6601A74327E00291744 /* ASScrollNode.h */, D785F6611A74327E00291744 /* ASScrollNode.m */, + B0F880581BEAEC7500D17647 /* ASTableNode.h */, + B0F880591BEAEC7500D17647 /* ASTableNode.m */, 055F1A3219ABD3E3004DAFF1 /* ASTableView.h */, 055F1A3319ABD3E3004DAFF1 /* ASTableView.mm */, AC7A2C161BDE11DF0093FE1A /* ASTableViewInternal.h */, @@ -1156,6 +1162,7 @@ 251B8EFB1BBB3D690087C538 /* ASDataController+Subclasses.h in Headers */, ACF6ED2A1B17843500DA7C62 /* ASLayoutable.h in Headers */, 9CDC18CC1B910E12004965E2 /* ASLayoutablePrivate.h in Headers */, + B0F8805A1BEAEC7500D17647 /* ASTableNode.h in Headers */, 464052241A3F83C40061C0BA /* ASLayoutController.h in Headers */, 9C5FA3511B8F6ADF00A62714 /* ASLayoutOptions.h in Headers */, 9C65A72A1BA8EA4D0084DA91 /* ASLayoutOptionsPrivate.h in Headers */, @@ -1594,6 +1601,7 @@ 058D0A1F195D050800B7D73C /* ASTextNodeTextKitHelpers.mm in Sources */, 058D0A20195D050800B7D73C /* ASTextNodeWordKerner.m in Sources */, ACC945AB1BA9E7C1005E1FB8 /* ASViewController.m in Sources */, + B0F8805B1BEAEC7500D17647 /* ASTableNode.m in Sources */, 205F0E221B376416007741D0 /* CGRect+ASConvenience.m in Sources */, 058D0A21195D050800B7D73C /* NSMutableAttributedString+TextKitAdditions.m in Sources */, 205F0E101B371875007741D0 /* UICollectionViewLayout+ASConvenience.m in Sources */, diff --git a/AsyncDisplayKit/ASTableNode.h b/AsyncDisplayKit/ASTableNode.h new file mode 100644 index 0000000000..9d9fa0d1b6 --- /dev/null +++ b/AsyncDisplayKit/ASTableNode.h @@ -0,0 +1,21 @@ +// +// ASTableNode.h +// AsyncDisplayKit +// +// Created by Steven Ramkumar on 11/4/15. +// Copyright © 2015 Facebook. All rights reserved. +// + +#import + +/** + * ASTableNode is a node based class that wraps an ASTableView. It can be used + * as a subnode of another node, and provide room for many (great) features and improvements later on. + */ +@interface ASTableNode : ASDisplayNode + +- (instancetype)initWithFrame:(CGRect)frame style:(UITableViewStyle)style asyncDataFetching:(BOOL)asyncDataFetchingEnabled NS_DESIGNATED_INITIALIZER; + +@property (nonatomic, readonly) ASTableView *view; + +@end diff --git a/AsyncDisplayKit/ASTableNode.m b/AsyncDisplayKit/ASTableNode.m new file mode 100644 index 0000000000..3b14cfb6c8 --- /dev/null +++ b/AsyncDisplayKit/ASTableNode.m @@ -0,0 +1,28 @@ +// +// ASTableNode.m +// AsyncDisplayKit +// +// Created by Steven Ramkumar on 11/4/15. +// Copyright © 2015 Facebook. All rights reserved. +// + +#import "ASTableNode.h" + +@implementation ASTableNode + +- (instancetype)initWithFrame:(CGRect)frame style:(UITableViewStyle)style asyncDataFetching:(BOOL)asyncDataFetchingEnabled +{ + if (self = [super initWithViewBlock:^UIView *{ + return [[ASTableView alloc] initWithFrame:frame style:style asyncDataFetching:asyncDataFetchingEnabled]; + }]) { + return self; + } + return nil; +} + +- (ASTableView *)view +{ + return (ASTableView *)[super view]; +} + +@end From a621e10a93e490200e09cbe59d6659fd41171956 Mon Sep 17 00:00:00 2001 From: Steven Ramkumar Date: Thu, 5 Nov 2015 08:59:41 -0800 Subject: [PATCH 5/9] Modify ASTableNode initializer --- AsyncDisplayKit/ASTableNode.h | 2 +- AsyncDisplayKit/ASTableNode.m | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/AsyncDisplayKit/ASTableNode.h b/AsyncDisplayKit/ASTableNode.h index 9d9fa0d1b6..026414be15 100644 --- a/AsyncDisplayKit/ASTableNode.h +++ b/AsyncDisplayKit/ASTableNode.h @@ -14,7 +14,7 @@ */ @interface ASTableNode : ASDisplayNode -- (instancetype)initWithFrame:(CGRect)frame style:(UITableViewStyle)style asyncDataFetching:(BOOL)asyncDataFetchingEnabled NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithStyle:(UITableViewStyle)style NS_DESIGNATED_INITIALIZER; @property (nonatomic, readonly) ASTableView *view; diff --git a/AsyncDisplayKit/ASTableNode.m b/AsyncDisplayKit/ASTableNode.m index 3b14cfb6c8..404d050865 100644 --- a/AsyncDisplayKit/ASTableNode.m +++ b/AsyncDisplayKit/ASTableNode.m @@ -10,10 +10,10 @@ @implementation ASTableNode -- (instancetype)initWithFrame:(CGRect)frame style:(UITableViewStyle)style asyncDataFetching:(BOOL)asyncDataFetchingEnabled +- (instancetype)initWithStyle:(UITableViewStyle)style { if (self = [super initWithViewBlock:^UIView *{ - return [[ASTableView alloc] initWithFrame:frame style:style asyncDataFetching:asyncDataFetchingEnabled]; + return [[ASTableView alloc] initWithFrame:CGRectZero style:style]; }]) { return self; } From e0f40d56443ec4ec2991c4dbc640f5d1102b24e0 Mon Sep 17 00:00:00 2001 From: Scott Goodson Date: Sat, 7 Nov 2015 23:08:53 -0800 Subject: [PATCH 6/9] Fix unusual cell content blanking issue when making existing cells much taller. --- AsyncDisplayKit/ASDisplayNode.h | 2 -- AsyncDisplayKit/ASDisplayNode.mm | 10 ---------- AsyncDisplayKit/Details/ASRangeHandlerRender.mm | 6 ++++++ 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/AsyncDisplayKit/ASDisplayNode.h b/AsyncDisplayKit/ASDisplayNode.h index ad86f873fb..916fad2945 100644 --- a/AsyncDisplayKit/ASDisplayNode.h +++ b/AsyncDisplayKit/ASDisplayNode.h @@ -646,7 +646,6 @@ typedef void (^ASDisplayNodeDidLoadBlock)(ASDisplayNode *node); * @param node The node to be added. */ - (void)addSubnode:(ASDisplayNode *)node; -- (NSString *)name; @end /** CALayer(AsyncDisplayKit) defines convenience method for adding sub-ASDisplayNode to a CALayer. */ @@ -657,7 +656,6 @@ typedef void (^ASDisplayNodeDidLoadBlock)(ASDisplayNode *node); * @param node The node to be added. */ - (void)addSubnode:(ASDisplayNode *)node; -- (NSString *)name; @end @interface ASDisplayNode (Deprecated) diff --git a/AsyncDisplayKit/ASDisplayNode.mm b/AsyncDisplayKit/ASDisplayNode.mm index dde440f2e2..28ba61e7c9 100644 --- a/AsyncDisplayKit/ASDisplayNode.mm +++ b/AsyncDisplayKit/ASDisplayNode.mm @@ -2190,11 +2190,6 @@ static const char *ASDisplayNodeAssociatedNodeKey = "ASAssociatedNode"; } } -- (NSString *)name -{ - return self.asyncdisplaykit_node.name; -} - @end @implementation CALayer (AsyncDisplayKit) @@ -2204,11 +2199,6 @@ static const char *ASDisplayNodeAssociatedNodeKey = "ASAssociatedNode"; [self addSublayer:node.layer]; } -- (NSString *)name -{ - return self.asyncdisplaykit_node.name; -} - @end diff --git a/AsyncDisplayKit/Details/ASRangeHandlerRender.mm b/AsyncDisplayKit/Details/ASRangeHandlerRender.mm index 0363abba2f..5e5eed9738 100644 --- a/AsyncDisplayKit/Details/ASRangeHandlerRender.mm +++ b/AsyncDisplayKit/Details/ASRangeHandlerRender.mm @@ -37,6 +37,12 @@ ASDisplayNodeAssertMainThread(); ASDisplayNodeAssert(rangeType == ASLayoutRangeTypeRender, @"Render delegate should not handle other ranges"); + // If a node had previously been onscreen but now is only in the working range, + // ensure its view is not orphaned in a UITableViewCell in the reuse pool. + if (![node isLayerBacked] && node.view.superview) { + [node.view removeFromSuperview]; + } + [node recursivelySetDisplaySuspended:NO]; // Add the node's layer to an off-screen window to trigger display and mark its contents as non-volatile. From efa47d65dd24212ca528334f20cbda5d3bc80446 Mon Sep 17 00:00:00 2001 From: Scott Goodson Date: Sat, 7 Nov 2015 23:29:36 -0800 Subject: [PATCH 7/9] Re-add name method to fix tests (grr). Clean up positioning of responder methods in header. --- AsyncDisplayKit/ASDisplayNode.h | 21 +++++++-------- AsyncDisplayKit/ASDisplayNode.mm | 44 ++++++++------------------------ 2 files changed, 22 insertions(+), 43 deletions(-) diff --git a/AsyncDisplayKit/ASDisplayNode.h b/AsyncDisplayKit/ASDisplayNode.h index 916fad2945..4c8ba651f2 100644 --- a/AsyncDisplayKit/ASDisplayNode.h +++ b/AsyncDisplayKit/ASDisplayNode.h @@ -506,16 +506,6 @@ typedef void (^ASDisplayNodeDidLoadBlock)(ASDisplayNode *node); */ - (CGRect)convertRect:(CGRect)rect fromNode:(ASDisplayNode *)node; -/** @name UIResponder methods */ - -// By default these fall through to the underlying view, but can be overridden. -- (BOOL)canBecomeFirstResponder; // default==NO -- (BOOL)becomeFirstResponder; // default==NO (no-op) -- (BOOL)canResignFirstResponder; // default==YES -- (BOOL)resignFirstResponder; // default==NO (no-op) -- (BOOL)isFirstResponder; -- (BOOL)canPerformAction:(SEL)action withSender:(id)sender; - @end @@ -614,6 +604,15 @@ typedef void (^ASDisplayNodeDidLoadBlock)(ASDisplayNode *node); @property (atomic, assign) CGFloat borderWidth; // default=0 @property (atomic, assign) CGColorRef borderColor; // default=opaque rgb black +// UIResponder methods +// By default these fall through to the underlying view, but can be overridden. +- (BOOL)canBecomeFirstResponder; // default==NO +- (BOOL)becomeFirstResponder; // default==NO (no-op) +- (BOOL)canResignFirstResponder; // default==YES +- (BOOL)resignFirstResponder; // default==NO (no-op) +- (BOOL)isFirstResponder; +- (BOOL)canPerformAction:(SEL)action withSender:(id)sender; + // Accessibility support @property (atomic, assign) BOOL isAccessibilityElement; @property (atomic, copy) NSString *accessibilityLabel; @@ -646,6 +645,7 @@ typedef void (^ASDisplayNodeDidLoadBlock)(ASDisplayNode *node); * @param node The node to be added. */ - (void)addSubnode:(ASDisplayNode *)node; +- (NSString *)name; @end /** CALayer(AsyncDisplayKit) defines convenience method for adding sub-ASDisplayNode to a CALayer. */ @@ -656,6 +656,7 @@ typedef void (^ASDisplayNodeDidLoadBlock)(ASDisplayNode *node); * @param node The node to be added. */ - (void)addSubnode:(ASDisplayNode *)node; +- (NSString *)name; @end @interface ASDisplayNode (Deprecated) diff --git a/AsyncDisplayKit/ASDisplayNode.mm b/AsyncDisplayKit/ASDisplayNode.mm index 28ba61e7c9..633f933d44 100644 --- a/AsyncDisplayKit/ASDisplayNode.mm +++ b/AsyncDisplayKit/ASDisplayNode.mm @@ -670,7 +670,7 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c) [self _addSubnodeViewsAndLayers]; } - [self recursivelyDisplayImmediately]; + [self recursivelyEnsureDisplay]; } } @@ -2043,35 +2043,6 @@ static void _recursivelySetDisplaySuspended(ASDisplayNode *node, CALayer *layer, } -- (BOOL)canBecomeFirstResponder { - return NO; -} - -- (BOOL)canResignFirstResponder { - return YES; -} - -- (BOOL)isFirstResponder { - ASDisplayNodeAssertMainThread(); - return _view != nil && [_view isFirstResponder]; -} - -// Note: this implicitly loads the view if it hasn't been loaded yet. -- (BOOL)becomeFirstResponder { - ASDisplayNodeAssertMainThread(); - return !self.layerBacked && [self canBecomeFirstResponder] && [self.view becomeFirstResponder]; -} - -- (BOOL)resignFirstResponder { - ASDisplayNodeAssertMainThread(); - return !self.layerBacked && [self canResignFirstResponder] && [_view resignFirstResponder]; -} - -- (BOOL)canPerformAction:(SEL)action withSender:(id)sender { - ASDisplayNodeAssertMainThread(); - return !self.layerBacked && [self.view canPerformAction:action withSender:sender]; -} - - (id)finalLayoutable { return self; @@ -2081,8 +2052,6 @@ static void _recursivelySetDisplaySuspended(ASDisplayNode *node, CALayer *layer, @implementation ASDisplayNode (Debugging) -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation" - (NSString *)description { if (self.name) { @@ -2091,7 +2060,6 @@ static void _recursivelySetDisplaySuspended(ASDisplayNode *node, CALayer *layer, return [super description]; } } -#pragma clang diagnostic pop - (NSString *)debugDescription { @@ -2190,6 +2158,11 @@ static const char *ASDisplayNodeAssociatedNodeKey = "ASAssociatedNode"; } } +- (NSString *)name +{ + return self.asyncdisplaykit_node.name; +} + @end @implementation CALayer (AsyncDisplayKit) @@ -2199,6 +2172,11 @@ static const char *ASDisplayNodeAssociatedNodeKey = "ASAssociatedNode"; [self addSublayer:node.layer]; } +- (NSString *)name +{ + return self.asyncdisplaykit_node.name; +} + @end From 3a4e9902e27976e15c730788222ebbf49a4e282a Mon Sep 17 00:00:00 2001 From: Scott Goodson Date: Sat, 7 Nov 2015 23:35:58 -0800 Subject: [PATCH 8/9] Remove a change that leaked from another diff in progress. --- AsyncDisplayKit/ASDisplayNode.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AsyncDisplayKit/ASDisplayNode.mm b/AsyncDisplayKit/ASDisplayNode.mm index 633f933d44..117749fea4 100644 --- a/AsyncDisplayKit/ASDisplayNode.mm +++ b/AsyncDisplayKit/ASDisplayNode.mm @@ -670,7 +670,7 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c) [self _addSubnodeViewsAndLayers]; } - [self recursivelyEnsureDisplay]; + [self recursivelyDisplayImmediately]; } } From 98010c4e1626f5d78b4f2cf43be5b93172e5c66e Mon Sep 17 00:00:00 2001 From: Scott Goodson Date: Sun, 8 Nov 2015 00:12:13 -0800 Subject: [PATCH 9/9] Include moved UIResponder methods in UIViewBridging Category Implementation. --- .../Private/ASDisplayNode+UIViewBridge.mm | 35 +++++++++++++++++++ .../Private/_ASHierarchyChangeSet.m | 4 +-- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/AsyncDisplayKit/Private/ASDisplayNode+UIViewBridge.mm b/AsyncDisplayKit/Private/ASDisplayNode+UIViewBridge.mm index 652c1fa890..c8089e9828 100644 --- a/AsyncDisplayKit/Private/ASDisplayNode+UIViewBridge.mm +++ b/AsyncDisplayKit/Private/ASDisplayNode+UIViewBridge.mm @@ -67,6 +67,41 @@ */ @implementation ASDisplayNode (UIViewBridge) +- (BOOL)canBecomeFirstResponder +{ + return NO; +} + +- (BOOL)canResignFirstResponder +{ + return YES; +} + +- (BOOL)isFirstResponder +{ + ASDisplayNodeAssertMainThread(); + return _view != nil && [_view isFirstResponder]; +} + +// Note: this implicitly loads the view if it hasn't been loaded yet. +- (BOOL)becomeFirstResponder +{ + ASDisplayNodeAssertMainThread(); + return !self.layerBacked && [self canBecomeFirstResponder] && [self.view becomeFirstResponder]; +} + +- (BOOL)resignFirstResponder +{ + ASDisplayNodeAssertMainThread(); + return !self.layerBacked && [self canResignFirstResponder] && [_view resignFirstResponder]; +} + +- (BOOL)canPerformAction:(SEL)action withSender:(id)sender +{ + ASDisplayNodeAssertMainThread(); + return !self.layerBacked && [self.view canPerformAction:action withSender:sender]; +} + - (CGFloat)alpha { _bridge_prologue; diff --git a/AsyncDisplayKit/Private/_ASHierarchyChangeSet.m b/AsyncDisplayKit/Private/_ASHierarchyChangeSet.m index d7c6ecab0b..ca6040f18c 100644 --- a/AsyncDisplayKit/Private/_ASHierarchyChangeSet.m +++ b/AsyncDisplayKit/Private/_ASHierarchyChangeSet.m @@ -91,7 +91,7 @@ case _ASHierarchyChangeTypeDelete: return _deleteSectionChanges; default: - NSAssert(NO, @"Request for section changes with invalid type: %lu", changeType); + NSAssert(NO, @"Request for section changes with invalid type: %lu", (long)changeType); } } @@ -106,7 +106,7 @@ case _ASHierarchyChangeTypeDelete: return _deleteItemChanges; default: - NSAssert(NO, @"Request for item changes with invalid type: %lu", changeType); + NSAssert(NO, @"Request for item changes with invalid type: %lu", (long)changeType); } }