Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RCTShadowView API broken in latest version 0.58.6 - iOS only #23806

Closed
windev92 opened this issue Mar 7, 2019 · 1 comment
Closed

RCTShadowView API broken in latest version 0.58.6 - iOS only #23806

windev92 opened this issue Mar 7, 2019 · 1 comment
Labels
Bug Platform: iOS iOS applications. Resolution: Locked This issue was locked by the bot.

Comments

@windev92
Copy link

windev92 commented Mar 7, 2019

Environment

React Native Environment Info:
System:
OS: macOS 10.14.3
CPU: (24) x64 Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz
Memory: 43.30 GB / 64.00 GB
Shell: 3.2.57 - /bin/bash
Binaries:
Node: 10.15.0 - /usr/local/bin/node
npm: 6.4.1 - /usr/local/bin/npm
Watchman: 4.9.0 - /usr/local/bin/watchman
SDKs:
iOS SDK:
Platforms: iOS 11.2, macOS 10.13, tvOS 11.2, watchOS 4.2
Android SDK:
API Levels: 16, 21, 23, 24, 26, 27, 28
Build Tools: 23.0.1, 26.0.2, 26.0.3, 27.0.3, 28.0.3
System Images: android-27 | Google APIs Intel x86 Atom, android-27 | Google Play Intel x86 Atom, android-28 | Google APIs Intel x86 Atom, android-28 | Google APIs Intel x86 Atom_64
IDEs:
Android Studio: 3.2 AI-181.5540.7.32.5056338
Xcode: 9.2/9C40b - /usr/bin/xcodebuild
npmPackages:
react: 16.6.3 => 16.6.3
react-native: 0.58.6 => 0.58.6
npmGlobalPackages:
react-native-cli: 2.0.1

Description

I am using the shadow view to locate the absolute coordinates of a component in the screen.
with 0.53.0 everything was fine, I was overriding applyLayoutNode and doing :

- (void)applyLayoutNode:(YGNodeRef)node
      viewsWithNewFrame:(NSMutableSet<RCTShadowView *> *)viewsWithNewFrame
       absolutePosition:(CGPoint)absolutePosition
{
       [_bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
        RCTMyView *view = (RCTMyView*)viewRegistry[self.reactTag];
        if ([view isKindOfClass:[RCTMyView class]]) {
            CGRect rect = CGRectMake(absolutePosition.x+YGNodeLayoutGetLeft(node), absolutePosition.y+YGNodeLayoutGetTop(node), YGNodeLayoutGetWidth(node), YGNodeLayoutGetHeight(node));
            [view updateComponent:rect];
        } else {
            RCTLogError(@"Cannot update button: %@ (tag #%@) is not RCTMyView", view, self.reactTag);
        }
    }];    
    [super applyLayoutNode:node viewsWithNewFrame:viewsWithNewFrame 
 absolutePosition:absolutePosition];
}

This function was only invoked when the layout requested a change, e.g screen rotation

with the next version, the interface has been broken in iOS only(still the same in android), so my code didn't compile anymore, which is something odd, since it's a public interface and obliged me to change my component code depending on the version. RCTView interface is not broken, otherwise most 3rd party components will not compile anymore.

With 0.55.4, I need to overwrite layoutWithMetrics :

- (void)layoutWithMetrics:(RCTLayoutMetrics)layoutMetrics
            layoutContext:(RCTLayoutContext)layoutContext {
    
    [_bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
        RCTMyView *view = (RCTMyView*)viewRegistry[self.reactTag];
        if ([view isKindOfClass:[RCTMyView class]]) {            
            // RN framework always adds 2 subviews to the rootView, the 3 anchored to the origin (0,0).
            // subv2 will be the parent of the view we declare in render()
            // --------------- rootView
            //    --------------- subv1
            //       --------------- subv2
            CGRect rect = layoutMetrics.frame;
            RCTShadowView* v = self.superview;
            while (v) {
                rect.origin.x += v.layoutMetrics.frame.origin.x;
                rect.origin.y += v.layoutMetrics.frame.origin.y;
                v = v.superview;
            }
            [view updateComponent:rect];
        } else {
            RCTLogError(@"Cannot update button: %@ (tag #%@) is not RCTMyView", view, self.reactTag);
        }
    }];
    
    [super layoutWithMetrics:layoutMetrics layoutContext:layoutContext];
}

This new function has 3 problems:

  1. it is periodically invoked, even if nothing has changed on screen
  2. it is not possible to get the absolute coordinates using the parameters layoutMetrics or layoutContext, without having to loop as I do here. Remember in 0.53.0 I was having the absolute position of the parent node...
  3. is there any plan to break this public interface again in the future? this will not be a viable solution for my client who will need a new release everytime the interface is changed
    It would be nice to have a react native core developper having a look at this.

This shadow interface has not been broken anymore until 0.58.6, and its android equivalent has never been broken(LayoutShadowNode)

THE PROBLEM IS STILL VALID IN LATEST RN VERSION. THE DESCRIPTION OF THE ISSUE
CLEARLY SHOWS A REGRESSION IN IOS ONLY, WHILE ANDROID IS OK. PLEASE FORWARD TO AN IOS RN CORE DEVELOPPER TO ADDRESS IT. KINDLY NOT CLOSE THE ISSUE WITHOUT BEEING ADDRESSED.

Reproducible Demo

use latest RN and see the regression.

@cpojer
Copy link
Contributor

cpojer commented Mar 19, 2019

Thank you for creating this issue. We are currently undergoing a major re-architecture and rewrite of React Native and many APIs are expected to change, see http://blog.nparashuram.com/2019/01/react-natives-new-architecture-glossary.html

At the moment, we cannot promise any particular APIs to stick around and unfortunately we will likely make major changes to things that you are using. However, if they are APIs that a majority of React Native users use, it also means that we at Facebook have to do a big migration and we will provide tools and guides for people to do the same migrations. I don't think it makes a ton of sense to overwrite this method, so in this case it seems like you may need to find a workaround.

@cpojer cpojer closed this as completed Mar 19, 2019
@facebook facebook locked as resolved and limited conversation to collaborators Mar 19, 2020
@react-native-bot react-native-bot added the Resolution: Locked This issue was locked by the bot. label Mar 19, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Bug Platform: iOS iOS applications. Resolution: Locked This issue was locked by the bot.
Projects
None yet
Development

No branches or pull requests

3 participants