react-native-push-notification / ios

React Native Push Notification API for iOS.
MIT License
745 stars 285 forks source link

How to implement @react-native-community/push-notification-ios with latest RN version 0.71.0 #388

Closed russelRajitha closed 1 year ago

russelRajitha commented 1 year ago

I have installed the latest version of React native and apparently, it has some changes with delegate files that we used to add push notification event handlers. so how to config this library with this latest version?

AppDelegate.h

#import <RCTAppDelegate.h>
#import <UIKit/UIKit.h>

@interface AppDelegate : RCTAppDelegate

@end
AppDelegate.mm

#import "AppDelegate.h"

#import <React/RCTBundleURLProvider.h>

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  self.moduleName = @"i4tEmployee";
  return [super application:application didFinishLaunchingWithOptions:launchOptions];
}

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

/// This method controls whether the `concurrentRoot`feature of React18 is turned on or off.
///
/// @see: https://reactjs.org/blog/2022/03/29/react-v18.html
/// @note: This requires to be rendering on Fabric (i.e. on the New Architecture).
/// @return: `true` if the `concurrentRoot` feature is enabled. Otherwise, it returns `false`.
- (BOOL)concurrentRootEnabled
{
  return true;
}

@end
erez-unitronics commented 1 year ago

You need to edit your AppDelegate.h file to look like this (Works for me):

#import <RCTAppDelegate.h>
#import <UIKit/UIKit.h>
#import <UserNotifications/UNUserNotificationCenter.h>

@interface AppDelegate : RCTAppDelegate <UNUserNotificationCenterDelegate>

@end
snurel commented 1 year ago

You need to edit your AppDelegate.h file to look like this (Works for me):

#import <RCTAppDelegate.h>
#import <UIKit/UIKit.h>
#import <UserNotifications/UNUserNotificationCenter.h>

@interface AppDelegate : RCTAppDelegate <UNUserNotificationCenterDelegate>

@end

Yes this is works for me too. When we take a look at the definition of 'RCTAppDelegate', we can see that it is already the same interface with previous version of RN (0.70.6).

@interface RCTAppDelegate : UIResponder <UIApplicationDelegate, RCTBridgeDelegate>
dezudas commented 1 year ago

You need to edit your AppDelegate.h file to look like this (Works for me):

#import <RCTAppDelegate.h>
#import <UIKit/UIKit.h>
#import <UserNotifications/UNUserNotificationCenter.h>

@interface AppDelegate : RCTAppDelegate <UNUserNotificationCenterDelegate>

@end

what about the changes to AppDelegate.mm

Bowlerr commented 1 year ago

any updates?

han-see commented 1 year ago

how does your App.Delegate.mm look like? Only changing the AppDelegate.h doesn't work for me. @erez-unitronics

erez-unitronics commented 1 year ago

@han-see @dezudas I didn't change anything special for the push notifications on my AppDelegate.m file, It looks like this:

#import "AppDelegate.h"

#import <React/RCTBundleURLProvider.h>
#import <React/RCTI18nUtil.h>

#import <UserNotifications/UserNotifications.h>
#import <RNCPushNotificationIOS.h>
#import <Firebase.h>

@implementation AppDelegate

(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[FIRApp configure];
[[RCTI18nUtil sharedInstance] allowRTL:NO];

// Define UNUserNotificationCenter
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
center.delegate = self;

self.moduleName = @"XXXXXXXXX";
// You can add your custom initial props in the dictionary below.
// They will be passed down to the ViewController used by React Native.
self.initialProps = @{};

return [super application:application didFinishLaunchingWithOptions:launchOptions];
}

//Called when a notification is delivered to a foreground app.
-(void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler
{
completionHandler(UNNotificationPresentationOptionSound | UNNotificationPresentationOptionAlert | UNNotificationPresentationOptionBadge);
}

// Required for the register event.

(void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
[RNCPushNotificationIOS didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
}
// 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
{
[RNCPushNotificationIOS didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
[[UNUserNotificationCenter currentNotificationCenter] setDelegate:self];
}
// Required for the registrationError event.
(void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
[RNCPushNotificationIOS didFailToRegisterForRemoteNotificationsWithError:error];
}
// Required for localNotification event
(void)userNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(UNNotificationResponse *)response
withCompletionHandler:(void (^)(void))completionHandler
{
[RNCPushNotificationIOS didReceiveNotificationResponse:response];
}
/// This method controls whether the concurrentRootfeature of React18 is turned on or off.
///
/// https://github.com/see: https://reactjs.org/blog/2022/03/29/react-v18.html
/// @note: This requires to be rendering on Fabric (i.e. on the New Architecture).
/// @return: true if the concurrentRoot feture is enabled. Otherwise, it returns false.

(BOOL)concurrentRootEnabled
{
// Switch this bool to turn on and off the concurrent root
return true;
}

(NSDictionary *)prepareInitialProps
{
NSMutableDictionary *initProps = [NSMutableDictionary new];
#ifdef RCT_NEW_ARCH_ENABLED
initProps[kRNConcurrentRoot] = @([self concurrentRootEnabled]);
#endif
return initProps;
}

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

@EnD
han-see commented 1 year ago

@erez-unitronics thank you so much for the information.

dezudas commented 1 year ago

@erez-unitronics thank you need to try

Bowlerr commented 1 year ago

After many attempts to get his working, turns out my issue was with my backend key being out of date...

For anyone who is wondering, these are my working files using AppDelegate.mm

AppDelegate.mm

#import "AppDelegate.h"
#import <React/RCTBundleURLProvider.h>
#import <UserNotifications/UserNotifications.h>
#import "RNSplashScreen.h"
#import "RNNotifications.h"

@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  self.moduleName = @"appName";
  // Create version variable and create props object
  NSString *version = [[[NSBundle mainBundle] infoDictionary] objectForKey: @"CFBundleShortVersionString"];

  // TODO: This usage of the DEBUG macro is a proxy for what we really want to
  // branch based on: the provisioning profile determined by Xcode for this build.
  // At worst, this could be obtained by reading the file 'embedded.mobileprovision'
  // here and searching its XML contents for the value of its 'aps-environment' key.
  // This is kind of a faff since embedded.mobileprovision is of a mixed encoding 
  // that is inconvenient to parse. In practice it may be fine to rely on DEBUG
  // in this way, but I should leave this comment here as a warning at least not to
  // remove it from the debug configuration.
  #if DEBUG
    self.initialProps = @{@"APNSEnvironment": @"development", @"Version": version};
  #else
    self.initialProps = @{@"APNSEnvironment": @"production", @"Version": version};
  #endif

  // Define UNUserNotificationCenter
  UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
  center.delegate = self;

  bool didFinish=[super application:application didFinishLaunchingWithOptions:launchOptions];
  [RNSplashScreen show];
  [RNNotifications startMonitorNotifications];
  return didFinish;
}

// Required for the register event.
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
 [RNNotifications didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler {
  [RNNotifications didReceiveBackgroundNotification:userInfo withCompletionHandler:completionHandler];
}

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

//Called when a notification is delivered to a foreground app.
-(void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler
{
  completionHandler(UNNotificationPresentationOptionSound | UNNotificationPresentationOptionAlert | UNNotificationPresentationOptionBadge);
}

- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
#if DEBUG
  return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"];
#else
  return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
#endif
}
/// This method controls whether the `concurrentRoot`feature of React18 is turned on or off.
///
/// @see: https://reactjs.org/blog/2022/03/29/react-v18.html
/// @note: This requires to be rendering on Fabric (i.e. on the New Architecture).
/// @return: `true` if the `concurrentRoot` feature is enabled. Otherwise, it returns `false`.
- (BOOL)concurrentRootEnabled
{
  return true;
}

@end

AppDelegate.h

#import <UserNotifications/UNUserNotificationCenter.h>
#import <RCTAppDelegate.h>
#import <UIKit/UIKit.h>

@interface AppDelegate : RCTAppDelegate <UNUserNotificationCenterDelegate>
@end

just replace @appName with your applications name. hope this is helpful :)

dezudas commented 1 year ago

@erez-unitronics Thank you it worked for me perfect

russelRajitha commented 1 year ago

Thank you all for the support and now its working with updated documentation.

choijiho0021 commented 1 year ago

You need to edit your AppDelegate.h file to look like this (Works for me):

#import <RCTAppDelegate.h>
#import <UIKit/UIKit.h>
#import <UserNotifications/UNUserNotificationCenter.h>

@interface AppDelegate : RCTAppDelegate <UNUserNotificationCenterDelegate>

@end

exactly perfect working thank you!!!!