From 82898b784e3b1e9be03a886dbb2cbc13236003f5 Mon Sep 17 00:00:00 2001 From: Adam Ernst Date: Tue, 12 May 2020 05:52:36 -0700 Subject: [PATCH] Clean up Flipper's iOS layout invalidation Summary: This reverts D21285438 and patches some holes in the layout invalidation routines. (I tried to use `didAddSubview:` and `willRemoveSubview:` but those are annoying for other reasons; for example, `willRemoveSubview:` can be called from within `dealloc` which is surprising. Also they still don't catch the case where subviews are being reordered.) Reviewed By: Andrey-Mishanin Differential Revision: D21512129 fbshipit-source-id: 1d9e8dac9333eddfae2309d446ef4de9e83220d6 --- .../FlipperKitLayoutPlugin.mm | 4 - .../FlipperKitLayoutPlugin/SKInvalidation.h | 1 - .../UIView+SKInvalidation.mm | 84 +++++++++++++------ 3 files changed, 59 insertions(+), 30 deletions(-) diff --git a/iOS/Plugins/FlipperKitLayoutPlugin/FlipperKitLayoutPlugin/FlipperKitLayoutPlugin.mm b/iOS/Plugins/FlipperKitLayoutPlugin/FlipperKitLayoutPlugin/FlipperKitLayoutPlugin.mm index 74d691a6d..cc6c23187 100644 --- a/iOS/Plugins/FlipperKitLayoutPlugin/FlipperKitLayoutPlugin/FlipperKitLayoutPlugin.mm +++ b/iOS/Plugins/FlipperKitLayoutPlugin/FlipperKitLayoutPlugin/FlipperKitLayoutPlugin.mm @@ -384,10 +384,6 @@ }); } -- (void)invalidateRootNode { - [self invalidateNode:_rootNode]; -} - - (void)_reportInvalidatedObjects { NSMutableArray* nodes = [NSMutableArray new]; { // scope mutex acquisition diff --git a/iOS/Plugins/FlipperKitLayoutPlugin/FlipperKitLayoutPlugin/SKInvalidation.h b/iOS/Plugins/FlipperKitLayoutPlugin/FlipperKitLayoutPlugin/SKInvalidation.h index f2eee5819..d37733d7b 100644 --- a/iOS/Plugins/FlipperKitLayoutPlugin/FlipperKitLayoutPlugin/SKInvalidation.h +++ b/iOS/Plugins/FlipperKitLayoutPlugin/FlipperKitLayoutPlugin/SKInvalidation.h @@ -10,7 +10,6 @@ @protocol SKInvalidationDelegate - (void)invalidateNode:(id)node; -- (void)invalidateRootNode; - (void)updateNodeReference:(id)node; @end diff --git a/iOS/Plugins/FlipperKitLayoutPlugin/FlipperKitLayoutPlugin/UIView+SKInvalidation.mm b/iOS/Plugins/FlipperKitLayoutPlugin/FlipperKitLayoutPlugin/UIView+SKInvalidation.mm index 662a8b6ed..d9e0f9989 100644 --- a/iOS/Plugins/FlipperKitLayoutPlugin/FlipperKitLayoutPlugin/UIView+SKInvalidation.mm +++ b/iOS/Plugins/FlipperKitLayoutPlugin/FlipperKitLayoutPlugin/UIView+SKInvalidation.mm @@ -23,6 +23,30 @@ FB_LINKABLE(UIView_SKInvalidation) [self class], @selector(setHidden:), @selector(swizzle_setHidden:)); swizzleMethods( [self class], @selector(addSubview:), @selector(swizzle_addSubview:)); + swizzleMethods( + [self class], + @selector(bringSubviewToFront:), + @selector(swizzle_bringSubviewToFront:)); + swizzleMethods( + [self class], + @selector(sendSubviewToBack:), + @selector(swizzle_sendSubviewToBack:)); + swizzleMethods( + [self class], + @selector(insertSubview:atIndex:), + @selector(swizzle_insertSubview:atIndex:)); + swizzleMethods( + [self class], + @selector(insertSubview:aboveSubview:), + @selector(swizzle_insertSubview:aboveSubview:)); + swizzleMethods( + [self class], + @selector(insertSubview:belowSubview:), + @selector(swizzle_insertSubview:belowSubview:)); + swizzleMethods( + [self class], + @selector(exchangeSubviewAtIndex:withSubviewAtIndex:), + @selector(swizzle_exchangeSubviewAtIndex:withSubviewAtIndex:)); swizzleMethods( [self class], @selector(removeFromSuperview), @@ -30,14 +54,6 @@ FB_LINKABLE(UIView_SKInvalidation) }); } -/** -This function takes in a view and returns true if the view is a UIWindow and its -windowLevel is an alert one otherwise it returns false. -*/ -static auto shouldInvalidateRootNode(UIView* view) -> bool { - return [view isKindOfClass:[UIWindow class]]; -} - - (void)swizzle_setHidden:(BOOL)hidden { [self swizzle_setHidden:hidden]; @@ -50,16 +66,40 @@ static auto shouldInvalidateRootNode(UIView* view) -> bool { - (void)swizzle_addSubview:(UIView*)view { [self swizzle_addSubview:view]; + [[SKInvalidation sharedInstance].delegate invalidateNode:self]; +} - id delegate = - [SKInvalidation sharedInstance].delegate; - if (delegate != nil) { - if (shouldInvalidateRootNode(view.superview)) { - [delegate invalidateRootNode]; - return; - } - [delegate invalidateNode:view.superview]; - } +- (void)swizzle_bringSubviewToFront:(UIView*)subview { + [self swizzle_bringSubviewToFront:subview]; + [[SKInvalidation sharedInstance].delegate invalidateNode:self]; +} + +- (void)swizzle_sendSubviewToBack:(UIView*)subview { + [self swizzle_sendSubviewToBack:subview]; + [[SKInvalidation sharedInstance].delegate invalidateNode:self]; +} + +- (void)swizzle_insertSubview:(UIView*)subview atIndex:(NSInteger)index { + [self swizzle_insertSubview:subview atIndex:index]; + [[SKInvalidation sharedInstance].delegate invalidateNode:self]; +} + +- (void)swizzle_insertSubview:(UIView*)subview + aboveSubview:(UIView*)siblingSubview { + [self swizzle_insertSubview:subview aboveSubview:siblingSubview]; + [[SKInvalidation sharedInstance].delegate invalidateNode:self]; +} + +- (void)swizzle_insertSubview:(UIView*)subview + belowSubview:(UIView*)siblingSubview { + [self swizzle_insertSubview:subview belowSubview:siblingSubview]; + [[SKInvalidation sharedInstance].delegate invalidateNode:self]; +} + +- (void)swizzle_exchangeSubviewAtIndex:(NSInteger)index1 + withSubviewAtIndex:(NSInteger)index2 { + [self swizzle_exchangeSubviewAtIndex:index1 withSubviewAtIndex:index2]; + [[SKInvalidation sharedInstance].delegate invalidateNode:self]; } - (void)swizzle_removeFromSuperview { @@ -68,14 +108,8 @@ static auto shouldInvalidateRootNode(UIView* view) -> bool { // before any early returns or mischief below! [self swizzle_removeFromSuperview]; - id delegate = - [SKInvalidation sharedInstance].delegate; - if (delegate != nil && oldSuperview != nil) { - if (shouldInvalidateRootNode(oldSuperview)) { - [delegate invalidateRootNode]; - return; - } - [delegate invalidateNode:oldSuperview]; + if (oldSuperview) { + [[SKInvalidation sharedInstance].delegate invalidateNode:oldSuperview]; } }