거의 알고리즘 일기장

react native screen에서 발견한 재미있는 부분 (react native의 native component에서 ui view controller 사용하는 테크닉) 본문

react-native

react native screen에서 발견한 재미있는 부분 (react native의 native component에서 ui view controller 사용하는 테크닉)

건우권 2024. 5. 19. 19:37

서문

최근에 회사에서 만든 앱이 강의를 보는 앱이었다. rn으로 하다보니 내가 원하는 모션을 정확하게 구현하기가 힘든 부분이 있었다.

 

조금 더 설명하자면, 비디오를 보고 있는중 세로모드 -> 가로모드(full screen) -> 세로모드로 갈때 하단의 자료 섹션(유튜브로 치면 비디오 info 부분)이 같이 돌아가는데, 나는 유튜브처럼 세로모드로 남아있어 줬으면 했다.

 

원하는 모션

첫번째 이미지를 보면 아래 info는 device의 orientation에 반응하지 않는다.

 

찾아본 바로는 해당 모션을 구현하기 위해서는 info에 해당하는 저 섹션이 supportedinterfaceorientations 라는 property를 사용해야 가능한것으로 보였다. 

그리고 문제를 해결하기 위해서 이런 의식의 흐름으로 찾아보았다.

 

-> 문제를 해결하기 위해서는 ui view controller를 추가하고 옵션을 바꿀수 있는 방법이 필요한거 같다! 

 

-> 하지만 react native의 기본 코어 컴포넌트들의 경우 ui view controller를 사용하는게 아니라 ui view를 사용한다.

 

-> 근데? xcode의 view hierarchy 에서 RNSCREEN 이라는 ui view controller는 뭘까? 이걸로 뭔가 커스텀 할수는 없을까?

 

-> 저게 뭘까하고 찾아봤더니 react navigation이 사용하는 react-native-screen (react-navigation 구현의 base 구현체로 보임) 이라는 친구가 보였다. screen을 만들때마다 생기는 ui view controller이다. 

 

-> 그리고 react native screen의 코드에서 RNSScreen 이라는 구현체를 확인해보았다.

https://github.com/software-mansion/react-native-screens/blob/main/ios/RNSScreen.mm

 

react-native-screens/ios/RNSScreen.mm at main · software-mansion/react-native-screens

Native navigation primitives for your React Native app. - software-mansion/react-native-screens

github.com


해당 코드에서 확인해볼 곳은 세곳이다.

1. RNSScreenManager(react native ios component 관련 코드)

2. RNScreenView(UIView)

3. RNScreen(UIViewController)

 

react native에서는 view의 형태로만 bridge를 할수 있다. 그러니 일단  RNSScreenManager에서 view는 어떻게 설정하는지 보자

 

RNScreen.mm의 일부

#ifdef RCT_NEW_ARCH_ENABLED
#else
- (UIView *)view
{
  return [[RNSScreenView alloc] initWithBridge:self.bridge];
}
#endif

+ (BOOL)requiresMainQueueSetup
{
  // Returning NO here despite the fact some initialization in -init method dispatches tasks
  // on main queue, because the comments in RN source code states that modules which return YES
  // here will be constructed ahead-of-time -- and this is not required in our case.
  return NO;
}

https://github.com/software-mansion/react-native-screens/blob/5301d3f226a80ec7983e49209e8cee505d3a2ae7/ios/RNSScreen.mm#L1489

 

react-native-screens/ios/RNSScreen.mm at 5301d3f226a80ec7983e49209e8cee505d3a2ae7 · software-mansion/react-native-screens

Native navigation primitives for your React Native app. - software-mansion/react-native-screens

github.com

해당 코드를 보면 view로는 RNScreenView를 사용하는것을 볼수 있다.

 

그리고 아래 코드를 확인해보면 알수 있듯이

view(RNSScreenManager) -> initWithBridge(RNSScreenView) -> initCommonProps(RNSScreenView) -> initWithView (RNSScreen)

이 순서로 호출되면서 react native에서 ios component를 사용할때 자연스레 ui view controller까지 생성되는걸 알수있다.

// RNSScreenView
@implementation RNSScreenView {
//...
- (instancetype)initWithBridge:(RCTBridge *)bridge
{
  if (self = [super init]) {
    _bridge = bridge;
    [self initCommonProps];
  }

  return self;
}

// RNSScreen initWithView 호출
- (void)initCommonProps
{
  _controller = [[RNSScreen alloc] initWithView:self];
  //... 
}

// RNSScreen에서 view를 받아서 생성
@implementation RNSScreen {
//...
- (instancetype)initWithView:(UIView *)view
{
  if (self = [super init]) {
    self.view = view;
    _fakeView = [UIView new];
    _shouldNotify = YES;
#ifdef RCT_NEW_ARCH_ENABLED
    _initialView = (RNSScreenView *)view;
#endif
  }
  return self;
}

 


여기서 알수 있는점

좀 귀찮긴 하지만, ui view controller의 옵션을 건드는 식의 커스텀이 필요하다면!..

react native에서 사용할 component를 만들어서 ui view controller를 연결시켜 놓는식의 구현체를 만든다면, react native의 yoga를 이용한 flex layout도 이용하면서 ui view controller를 붙여서 옵션 커스텀도 가능하다~ (물론 js side에서 option 설정을 하는식의 구현은 안됨 조금 더 생각해보니까 react native module의 특정함수를 호출하고 해당 모듈 내에서 해당 Ui view controller의 인스턴스를 가져와서 옵션 설정정도는 되지 않을까?.. ) 정도의 인사이트를 얻었다.


결론

일단은 안하기로..ㅎㅎ

 

 

 

 

반응형
Comments