Skip to content

RCTShadowView API broken after 0.53.0 (iOS only) #23232

Description

@windev92

Environment

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.

Reproducible Demo

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Platform: iOSiOS applications.Ran CommandsOne of our bots successfully processed a command.Resolution: LockedThis issue was locked by the bot.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions