Skip to content

RCTShadowView API broken after 0.53.0 (iOS only) #23232

Closed
@windev92

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

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