Skip to content

App Crashes with message "-[RCTView setSheetLargestUndimmedDetent:]: unrecognized selector sent to instance" #2166

Open
@hoonjoo-park

Description

Description

Problem

First of all, I've integrated ReactNative with my iOS native App.
There is no problem with using the basic components of ReactNative. However, when I register RootStackNavigator as an entryPoint, the app crashes with the following error:

-[RCTView setSheetLargestUndimmedDetent:]: unrecognized selector sent to instance

As I said above, my app is based on iOS, and only a few screens are implemented with ReactNative.
so I had to implement my custom BridgeManager which returns rootViewFactory to render ReactNative View.


React Native Code Example:

index.js

const { AppRegistry } = require('react-native')
import 'react-native-gesture-handler'
import 'react-native-reanimated'
import NoticeRootStackNavigator from './src/navigation/notice/NoticeRootStackNavigator'

AppRegistry.registerComponent('NoticeList', () => NoticeRootStackNavigator)

NoticeRootStackNavigator

export type NoticeStackParamList = {
  NoticeList: undefined;
  NoticeDetail: undefined;
}

export type NoticeNavigationProp = StackNavigationProp<NoticeStackParamList>;

const NoticeStack = createStackNavigator<NoticeStackParamList>();

const NoticeRootStackNavigator = () => {
  const screenOptions = useNavigatorScreenOptions();

  return (
    <NavigationContainer>
      <NoticeStack.Navigator screenOptions={screenOptions} initialRouteName="NoticeList">
        <NoticeStack.Screen name="NoticeList" component={NoticeList} />
        <NoticeStack.Screen name="NoticeDetail" component={NoticeDetail} />
      </NoticeStack.Navigator>
    </NavigationContainer>
  );
}

export default memo(NoticeRootStackNavigator);

iOS Code Example

CustomRCTBridgeManager.mm

#import "CustomRCTBridgeManager.h"
#import "RCTAppSetupUtils.h"
#import <React/RCTComponentViewFactory.h>
#import <React/CoreModulesPlugins.h>

@interface CustomRCTBridgeManager () <RCTTurboModuleManagerDelegate>
@end


@implementation CustomRCTBridgeManager

+ (instancetype)shared {
    static CustomRCTBridgeManager *shared = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        shared = [[self alloc] init];
    });
    return shared;
}

- (instancetype)init {
    self = [super init];
    if (self) {
        [self configureBridge];
    }
    return self;
}

- (void)configureBridge {
    _rootViewFactory = [self createRCTRootViewFactory];
    _bridge = _rootViewFactory.bridge;
}

- (UIView *)createRootView: (NSString *)moduleName andInitialProperties:(NSDictionary * _Nullable)initialProperties {
    if (initialProperties == nil) {
        initialProperties = self.initialProps;
    }
    
    return [self.rootViewFactory viewWithModuleName:moduleName
                                  initialProperties:initialProperties
                                      launchOptions:nil];
}

- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge {
#if DEBUG
    return [NSURL URLWithString:@"http://localhost:8081/index.bundle?platform=ios"];
#else
    return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];

#endif
}

#pragma mark - New Arch Enabled settings

- (BOOL)newArchEnabled
{
#if RCT_NEW_ARCH_ENABLED
    return YES;
#else
    return NO;
#endif
}

- (BOOL)turboModuleEnabled
{
    return [self newArchEnabled];
}

- (BOOL)fabricEnabled
{
    return [self newArchEnabled];
}

- (BOOL)bridgelessEnabled
{
    return [self newArchEnabled];
}

#pragma mark - RCTTurboModuleManagerDelegate

- (id<RCTTurboModule>)getModuleInstanceFromClass:(Class)moduleClass
{
    return RCTAppSetupDefaultModuleFromClass(moduleClass);
}

- (Class)getModuleClassFromName:(const char *)name {
#if RN_DISABLE_OSS_PLUGIN_HEADER
    return RCTTurboModulePluginClassProvider(name);
#else
    return RCTCoreModulesClassProvider(name);
#endif
}

- (RCTRootViewFactory *)createRCTRootViewFactory
{
    __weak __typeof(self) weakSelf = self;
    RCTBundleURLBlock bundleUrlBlock = ^{
        return [weakSelf sourceURLForBridge:weakSelf.bridge];
    };
    
    RCTRootViewFactoryConfiguration *configuration =
    [[RCTRootViewFactoryConfiguration alloc] initWithBundleURLBlock:bundleUrlBlock
                                                     newArchEnabled:self.fabricEnabled
                                                 turboModuleEnabled:self.turboModuleEnabled
                                                  bridgelessEnabled:self.bridgelessEnabled];
    
    return [[RCTRootViewFactory alloc] initWithConfiguration:configuration andTurboModuleManagerDelegate:self];
}

@end

NoticeViewController

final class NoticeListViewController: ReactNativeViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        self.navigationItem.title = "NoticeList"
        
        configureRCTView()
    }
    
    
    private func configureRCTView() {
        guard let bridgeManager = QandaRCTBridgeManager.shared() else { return }
        
        let reactView = bridgeManager.createRootView(ReactNativeScreen.notice, andInitialProperties: nil)
        
        self.view = reactView
    }
}

Steps to reproduce

  1. enable new architecture by running RCT_NEW_ARCH_ENABLED=1 bundle exec pod install
  2. navigate to ViewController which it's view is RNScreen
  3. it successfully loads bundle from metro server
  4. after loading finished, app crashes.

Snack or a link to a repository

sorry it's my company's private repo

Screens version

3.31.1

React Native version

0.74.2

Platforms

iOS

JavaScript runtime

Hermes

Workflow

React Native (without Expo)

Architecture

Fabric (New Architecture)

Build type

Debug mode

Device

iOS simulator

Device model

iPhone 15 Pro

Acknowledgements

Yes

Metadata

Assignees

Labels

Missing infoThe user didn't precise the problem enoughMissing reproThis issue need minimum repro scenarioPlatform: iOSThis issue is specific to iOS

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions