[unimodules] App doesn’t launch on RN 0.62.2

I’ve tried to set-up unimodules on a bare RN 0.62.2 project. During the configuration process, I’ve already encountered some differences to the documentation (especially when it comes to Flipper, which has newly been implemented in RN 0.62 and was missing in the example AppDelegate files).
These are my AppDelegate.m and AppDelegate.h as of now:

AppDelegate.m

#import "AppDelegate.h"

#import <React/RCTBridge.h>
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>

#import <UMCore/UMModuleRegistry.h>
#import <UMReactNativeAdapter/UMNativeModulesProxy.h>
#import <UMReactNativeAdapter/UMModuleRegistryAdapter.h>

#if DEBUG
#import <FlipperKit/FlipperClient.h>
#import <FlipperKitLayoutPlugin/FlipperKitLayoutPlugin.h>
#import <FlipperKitUserDefaultsPlugin/FKUserDefaultsPlugin.h>
#import <FlipperKitNetworkPlugin/FlipperKitNetworkPlugin.h>
#import <SKIOSNetworkPlugin/SKIOSNetworkAdapter.h>
#import <FlipperKitReactPlugin/FlipperKitReactPlugin.h>

static void InitializeFlipper(UIApplication *application) {
  FlipperClient *client = [FlipperClient sharedClient];
  SKDescriptorMapper *layoutDescriptorMapper = [[SKDescriptorMapper alloc] initWithDefaults];
  [client addPlugin:[[FlipperKitLayoutPlugin alloc] initWithRootNode:application withDescriptorMapper:layoutDescriptorMapper]];
  [client addPlugin:[[FKUserDefaultsPlugin alloc] initWithSuiteName:nil]];
  [client addPlugin:[FlipperKitReactPlugin new]];
  [client addPlugin:[[FlipperKitNetworkPlugin alloc] initWithNetworkAdapter:[SKIOSNetworkAdapter new]]];
  [client start];
}
#endif

@interface AppDelegate () <RCTBridgeDelegate>

@property (nonatomic, strong) UMModuleRegistryAdapter *moduleRegistryAdapter;

@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  self.moduleRegistryAdapter = [[UMModuleRegistryAdapter alloc] initWithModuleRegistryProvider:[[UMModuleRegistryProvider alloc] init]];
  
#if DEBUG
  InitializeFlipper(application);
#endif

  RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
  RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
                                                   moduleName:@"internationalsos"
                                            initialProperties:nil];

  rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];

  self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
  UIViewController *rootViewController = [UIViewController new];
  rootViewController.view = rootView;
  self.window.rootViewController = rootViewController;
  [self.window makeKeyAndVisible];
  [super application:application didFinishLaunchingWithOptions:launchOptions];
  return YES;
}

- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
#if DEBUG
  return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
#else
  return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
#endif
}

- (NSArray<id<RCTBridgeModule>> *)extraModulesForBridge:(RCTBridge *)bridge
{
    NSArray<id<RCTBridgeModule>> *extraModules = [_moduleRegistryAdapter extraModulesForBridge:bridge];
    // If you'd like to export some custom RCTBridgeModules that are not Expo modules, add them here!
    return extraModules;
}

@end

AppDelegate.h

#import <React/RCTBridgeDelegate.h>
#import <UIKit/UIKit.h>
#import <UMCore/UMAppDelegateWrapper.h>

@interface AppDelegate : UMAppDelegateWrapper <UIApplicationDelegate, RCTBridgeDelegate>

@property (nonatomic, strong) UIWindow *window;

@end

The app does not launch whatsoever. When run from Xcode, it crashes in Pods/FlipperKit/FlipperKitUserDefaultsPlugin/FKUserDefaultsSwizzleUtility.m in line 62 with the code EXC_BAD_ACCESS:

      if (blk != nil) {
        NSString* originalStr =
            [@"comfacebookFlipperKit_" stringByAppendingString:selStr];
        [invocation setSelector:NSSelectorFromString(originalStr)];
        block(invocation); // Crash
      } else {
        ((void (*)(id, SEL, NSInvocation*))orig)(this, fwdSel, invocation);
      }

Here’s the dump from the console:

2020-06-08 09:50:38.626942+0200 Intl. SOS TeleDoctor24[15636:4330951] You've implemented -[<UIApplicationDelegate> application:performFetchWithCompletionHandler:], but you still need to add "fetch" to the list of your supported UIBackgroundModes in your Info.plist.
2020-06-08 09:50:38.626982+0200 Intl. SOS TeleDoctor24[15636:4330951] You've implemented -[<UIApplicationDelegate> application:didReceiveRemoteNotification:fetchCompletionHandler:], but you still need to add "remote-notification" to the list of your supported UIBackgroundModes in your Info.plist.
flipper: FlipperClient::addPlugin Inspector
flipper: FlipperClient::addPlugin Preferences
flipper: FlipperClient::addPlugin React
flipper: FlipperClient::addPlugin Network
2020-06-08 09:50:39.000 [info][tid:main][RCTRootView.m:294] Running application internationalsos ({
    initialProps =     {
    };
    rootTag = 1;
})
(lldb) 

(I’ve already tried to add the two background modes by the way.)
When I disable the line InitializeFlipper(application) in AppDelegate.m, the app then crashes in main.m in line 7:

#import <UIKit/UIKit.h>

#import "AppDelegate.h"

int main(int argc, char * argv[]) {
  @autoreleasepool {
    return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); // Crash
  }
}

2 thoughts on “[unimodules] App doesn’t launch on RN 0.62.2

  1. Confirming immediate crash on iOS bare workflow project when setting up due to unimodules setup instruction.

    @sjchmiela The new instruction(#8683) is much better than previous one, but I guess something is missed in it, bc it leads to crash…

    Logs:

    Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
    0 com.xxx.app 0x000000010189d004 __60-[FKUserDefaultsSwizzleUtility swizzleSelector:class:block:]_block_invoke + 388 (FKUserDefaultsSwizzleUtility.m:62)
    1 com.xxx.app 0x0000000101d3c7b4 -[UMAppDelegateWrapper forwardInvocation:] + 404 (UMAppDelegateWrapper.m:25)
    2 com.apple.CoreFoundation 0x00007fff23c759f6 ___forwarding___ + 838
    3 com.apple.CoreFoundation 0x00007fff23c77f78 _CF_forwarding_prep_0 + 120
    4 com.xxx.app 0x00000001012d2efb -[AppDelegate application:didFinishLaunchingWithOptions:] + 763 (AppDelegate.m:59)
    

    UPDATE: Instruction works with the latest expo-unimodules@next, but fails with current stable issue.

  2. To fix the problem in @MrFaisal100‘s project I “just” had to ensure that a recent fix to @unimodules/core is present — #8526.

    It adds a window property setter to UMAppDelegateWrapper, the application was crashing due to it missing, see the screenshot:

    Zrzut ekranu 2020-06-10 o 14 33 29

    In the lower center section you can see selStr equal to "setWindow:", which means that Flipper tries to set the window property.

    So, for some (at least) of you, upgrading to react-native-unimodules@0.10.1 (it’s available under next tag on NPM already and corresponds to the upcoming SDK 38) should fix the issue. If you’d rather just upgrade @unimodules/core (should be safe), just add it at version ~5.3.0.

    To verify if that will fix it, go to UMAppDelegateWrapper.m file (Cmd + Shift + o, enter “UMAppDelegate”, select .m and hit enter) and then, add:

     static dispatch_once_t onceToken;
     
     @implementation UMAppDelegateWrapper
    +
    +@synthesize window = _window;
     
     - (void)forwardInvocation:(NSInvocation *)invocation {