invertase / react-native-firebase

🔥 A well-tested feature-rich modular Firebase implementation for React Native. Supports both iOS & Android platforms for all Firebase services.
https://rnfirebase.io
Other
11.53k stars 2.18k forks source link

[🐛] Assigning to 'id<FIRMessagingDelegate> _Nullable' #6396

Closed ThushalIntervest closed 1 year ago

ThushalIntervest commented 1 year ago

When Upgrade React Native 0.64.2 -> 0.68.2 and Firebase 14.8.1 to 15.1.1

I Got this error in xcode for this line in AppDelegate.mm

[FIRMessaging messaging].delegate = self;

ERROR MESSAGE : Assigning to 'id _Nullable' from incompatible type 'AppDelegate *const __strong'

Screenshot 2022-07-18 at 00 15 27

Do you have any solution for this ?

mikehardy commented 1 year ago

Interesting, our e2e test harness uses the rn68+rnfb15 combo and compiles fine.

This script does work also, but on rn69 https://github.com/mikehardy/rnfbdemo/blob/main/make-demo.sh

In general I do not reproduce these issues with default xcode settings as they come from react-native template. If you can make a reproduction or point out some setting to trigger it we can investigate

ThushalIntervest commented 1 year ago

Here is the AppDelegate and podFile. the issue was not there in React Native 0.64.2 and Firebase 14.8.1. After updating React Native 0.68.2 and Firebase 15.1.1 iOS Firebase Notification also not working when commenting that issue Line. can you please explain how to solve this issue? 🙏

AppDelegate.mm

#import "AppDelegate.h"

#if RCT_DEV
#import <React/RCTDevLoadingView.h>
#endif

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

#import <TSBackgroundFetch/TSBackgroundFetch.h>
//#import <Firebase.h>
#import "RNSplashScreen.h"
#import <GoogleMaps/GoogleMaps.h>
#import <React/RCTLinkingManager.h>
#import <UserNotifications/UserNotifications.h>
#import <RNCPushNotificationIOS.h>
#import <RNAppsFlyer.h>
#import <Firebase.h>
#import <AppsFlyerLib.h>

#if RCT_NEW_ARCH_ENABLED
#import <React/CoreModulesPlugins.h>
#import <React/RCTCxxBridgeDelegate.h>
#import <React/RCTFabricSurfaceHostingProxyRootView.h>
#import <React/RCTSurfacePresenter.h>
#import <React/RCTSurfacePresenterBridgeAdapter.h>
#import <ReactCommon/RCTTurboModuleManager.h>
#import <react/config/ReactNativeConfig.h>

@interface AppDelegate () <RCTCxxBridgeDelegate, RCTTurboModuleManagerDelegate> {
  RCTTurboModuleManager *_turboModuleManager;
  RCTSurfacePresenterBridgeAdapter *_bridgeAdapter;
  std::shared_ptr<const facebook::react::ReactNativeConfig> _reactNativeConfig;
  facebook::react::ContextContainer::Shared _contextContainer;
}
@end
#endif

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{

  RCTAppSetupPrepareApp(application);

  RCTBridge *bridge = [self.reactDelegate createBridgeWithDelegate:self launchOptions:launchOptions];

#if RCT_NEW_ARCH_ENABLED
  _contextContainer = std::make_shared<facebook::react::ContextContainer const>();
  _reactNativeConfig = std::make_shared<facebook::react::EmptyReactNativeConfig const>();
  _contextContainer->insert("ReactNativeConfig", _reactNativeConfig);
  _bridgeAdapter = [[RCTSurfacePresenterBridgeAdapter alloc] initWithBridge:bridge contextContainer:_contextContainer];
  bridge.surfacePresenter = _bridgeAdapter.surfacePresenter;
#endif

  // Start I added
    [FIRApp configure];

    if ([UNUserNotificationCenter class] != nil) {
      // iOS 10 or later
      // For iOS 10 display notification (sent via APNS)
      [UNUserNotificationCenter currentNotificationCenter].delegate = self;
      UNAuthorizationOptions authOptions = UNAuthorizationOptionAlert |
          UNAuthorizationOptionSound | UNAuthorizationOptionBadge;
      [[UNUserNotificationCenter currentNotificationCenter]
          requestAuthorizationWithOptions:authOptions
          completionHandler:^(BOOL granted, NSError * _Nullable error) {
            // ...
          }];
    } else {
      // iOS 10 notifications aren't available; fall back to iOS 8-9 notifications.
      UIUserNotificationType allNotificationTypes =
      (UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge);
      UIUserNotificationSettings *settings =
      [UIUserNotificationSettings settingsForTypes:allNotificationTypes categories:nil];
      [application registerUserNotificationSettings:settings];
    }

    [application registerForRemoteNotifications];

    [FIRMessaging messaging].autoInitEnabled = YES;
    [FIRMessaging messaging].delegate = self;

  // End I added

  #if RCT_DEV
  [bridge moduleForClass:[RCTDevLoadingView class]];
  #endif
  UIView *rootView = [self.reactDelegate createRootViewWithBridge:bridge moduleName:@"rrrr" 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 = [self.reactDelegate createRootViewController];
  rootViewController.view = rootView;
  self.window.rootViewController = rootViewController;
  [self.window makeKeyAndVisible];
  // Define UNUserNotificationCenter
  UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
  center.delegate = self;
  //[RNSplashScreen show];
 [RNSplashScreen showSplash:@"LaunchScreen" inRootView:rootView];

  // [REQUIRED] Register BackgroundFetch
  [[TSBackgroundFetch sharedInstance] didFinishLaunching];
  [super application:application didFinishLaunchingWithOptions:launchOptions];
  return YES;
}

// Start I added

- (void)messaging:(FIRMessaging *)messaging didReceiveRegistrationToken:(NSString *)fcmToken {
    NSLog(@"FCM registration token: %@", fcmToken);
    // Notify about received token.
    NSDictionary *dataDict = [NSDictionary dictionaryWithObject:fcmToken forKey:@"token"];
    [[NSNotificationCenter defaultCenter] postNotificationName:
     @"FCMToken" object:nil userInfo:dataDict];
}

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
  [FIRMessaging messaging].APNSToken = deviceToken;
  [RNCPushNotificationIOS didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
  // notify AppsFlyerLib
  [[AppsFlyerLib shared] registerUninstall:deviceToken];
}

- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
{
  [RNCPushNotificationIOS didRegisterUserNotificationSettings:notificationSettings];
}

// Required for the notification event. You must call the completion handler after handling the remote notification.
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
  [[FIRMessaging messaging] appDidReceiveMessage:userInfo];
  [RNCPushNotificationIOS didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
}

// Required for the registrationError event.
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
  [RNCPushNotificationIOS didFailToRegisterForRemoteNotificationsWithError:error];
}

// Required for the localNotification event.
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
  [RNCPushNotificationIOS didReceiveLocalNotification:notification];
}

// Called when a notification is delivered to a foreground app.
-(void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler
  {
    NSDictionary *userInfo = notification.request.content.userInfo;
    [[FIRMessaging messaging] appDidReceiveMessage:userInfo];
    completionHandler(UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionBadge);
  }

//Called when a user taps on a notification in the foreground
-(void)userNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(nonnull void (^)(void))completionHandler
{
  NSMutableDictionary *userData = [NSMutableDictionary dictionaryWithDictionary:response.notification.request.content.userInfo];
  [userData setObject:@(1) forKey:@"openedInForeground"];
  [RNCPushNotificationIOS didReceiveRemoteNotification:userData];
  completionHandler();
}

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

#if RCT_NEW_ARCH_ENABLED

#pragma mark - RCTCxxBridgeDelegate

- (std::unique_ptr<facebook::react::JSExecutorFactory>)jsExecutorFactoryForBridge:(RCTBridge *)bridge
{
  _turboModuleManager = [[RCTTurboModuleManager alloc] initWithBridge:bridge
                                                             delegate:self
                                                            jsInvoker:bridge.jsCallInvoker];
  return RCTAppSetupDefaultJsExecutorFactory(bridge, _turboModuleManager);
}

#pragma mark RCTTurboModuleManagerDelegate

- (Class)getModuleClassFromName:(const char *)name
{
  return RCTCoreModulesClassProvider(name);
}

- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:(const std::string &)name
                                                      jsInvoker:(std::shared_ptr<facebook::react::CallInvoker>)jsInvoker
{
  return nullptr;
}

- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:(const std::string &)name
                                                     initParams:
                                                         (const facebook::react::ObjCTurboModule::InitParams &)params
{
  return nullptr;
}

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

#endif

- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url
 options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
{
  // version >= 6.2.10
  [[AppsFlyerAttribution shared] handleOpenUrl:url options:options];
  return [RCTLinkingManager application:app openURL:url options:options];
}

- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity
 restorationHandler:(void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler
{
  // version >= 6.2.10 Appslyer
  [[AppsFlyerAttribution shared] continueUserActivity:userActivity restorationHandler:restorationHandler];

  return [RCTLinkingManager application:application
                   continueUserActivity:userActivity
                     restorationHandler:restorationHandler];
}

@end

PodFile

require File.join(File.dirname(`node --print "require.resolve('expo/package.json')"`), "scripts/autolinking")
require_relative '../node_modules/react-native/scripts/react_native_pods'
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'

platform :ios, '12.0'
install! 'cocoapods', :deterministic_uuids => false

project 'rrrr', {
  'DebugDev' => :debug,
  'DebugStaging' => :debug,
  'DebugProd' => :debug,
  'ReleaseDev' => :release,
  'ReleaseStaging' => :release,
  'ReleaseProd' => :release,
}

debugs = ['DebugDev','DebugStaging','DebugProd']

target 'rrrr' do
  use_expo_modules!
  post_integrate do |installer|
    begin
      expo_patch_react_imports!(installer)
    rescue => e
      Pod::UI.warn e
    end
  end
  rn_maps_path = '../node_modules/react-native-maps'
  pod 'react-native-google-maps', :path => rn_maps_path
  pod 'GoogleMaps'
  pod 'Google-Maps-iOS-Utils'
  pod 'Firebase', :modular_headers => true
  pod 'FirebaseCore', :modular_headers => true
  pod 'GoogleUtilities', :modular_headers => true
  $RNFirebaseAsStaticFramework = true
  config = use_native_modules!

  # Flags change depending on the env values.
  flags = get_default_flags()

  use_react_native!(
:path => config["reactNativePath"],
    # to enable hermes on iOS, change `false` to `true` and then install pods
    :hermes_enabled => flags[:hermes_enabled],
    :fabric_enabled => flags[:fabric_enabled],
    # An absolute path to your application root.
    :app_path => "#{Pod::Config.instance.installation_root}/.."
)
  permissions_path = '../node_modules/react-native-permissions/ios'

  pod 'Permission-Notifications', :path => "#{permissions_path}/Notifications"

  target 'rrrrTests' do
    inherit! :complete
    # Pods for testing
  end

end

target 'rrrr-tvOS' do
  # Pods for rrrr-tvOS

  target 'rrrr-tvOSTests' do
    inherit! :search_paths
    # Pods for testing
  end
end
mikehardy commented 1 year ago

I can't tell you how to solve the issue unfortunately, most of my earlier comment still stands / has not been addressed:


Interesting, our e2e test harness uses the rn68+rnfb15 combo and compiles fine.

This script does work also, but on rn69 https://github.com/mikehardy/rnfbdemo/blob/main/make-demo.sh

In general I do not reproduce these issues with default xcode settings as they come from react-native template. If you can make a reproduction or point out some setting to trigger it we can investigate

ThushalIntervest commented 1 year ago

I actually got the solution using put this code Line above the Error line

@interface AppDelegate() <FIRMessagingDelegate>
@end

I reproduce it when Updating the React Native 0.64.2V to 0.68.2V and Firebase 14.8.1 to 15.1.1

mikehardy commented 1 year ago

I understand you can reproduce this. What I struggle with is that I have a fully scripted demo from npx react-native init, and it does not show up. So I need a reproduction from first principles, or the exact setting in xcode that causes this to show up.

Repeating "I reproduce this" without posting your reproduction as a repo, while I have posted a scripted reproduction from scratch that does not reproduce it means I've got the evidence posted and you have not, so I don't know how to move this forward

ThushalIntervest commented 1 year ago

Okay, Thank you. I found a solution for this bug.