Our venture is developed utilizing Expo (ReactNative). Used expo’s prebuild
command to generate the android and ios codes. We deliberate to make use of the Klaviyo for push notifications.
We’re utilizing the SDK : klaviyo-react-native-sdk
When applied, we confronted points with configuration. So referred the instance code right here:
I used to be capable of get the Android working(and was capable of check the push notifications), however the iOS is failing the construct after I run yarn run ios
.
Have been spending greater than 3 weeks simply to get this resolved.
AppDelegate.h:
#import
#import
#import
#import
// @interface AppDelegate : EXAppDelegateWrapper
// iOS Set up Step 1: Conform AppDelegate to UNUserNotificationCenterDelegate
// @interface AppDelegate: RCTAppDelegate
@interface AppDelegate : EXAppDelegateWrapper
@finish
AppDelegate.mm:
#import "AppDelegate.h"
#import
#import
@implementation AppDelegate
//-- ABC - Change to NO if you do not need debug alerts or logs.
BOOL isDebug = YES;
//-- ABC - Change to NO for those who desire to initialize and deal with push tokens within the React Native layer
BOOL useNativeImplementation = YES;
- (BOOL)utility:(UIApplication *)utility didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.moduleName = @"principal";
// You may add your customized preliminary props within the dictionary beneath.
// They are going to be handed all the way down to the ViewController utilized by React Native.
self.initialProps = @{};
//-- ABC - iOS Set up Step 2: Set the UNUserNotificationCenter delegate to self
[UNUserNotificationCenter currentNotificationCenter].delegate = self;
//-- ABC
if (useNativeImplementation) {
// iOS Set up Step 3: Initialize the SDK with public key, if initializing from native code
// Exclude if initializing from react native layer
[PushNotificationsHelper initializeSDK: @"XXXXXX"];
// iOS Set up Step 4: Request notification permission from the person
// Exclude if dealing with permissions from react native layer
[PushNotificationsHelper requestNotificationPermission];
} else {
// Initialize cross-platform push library, e.g. Firebase
}
//-- ABC - confer with set up step 16 beneath
NSMutableDictionary * launchOptionsWithURL = [self getLaunchOptionsWithURL:launchOptions];
// return [super application:application didFinishLaunchingWithOptions:launchOptions];
return [super application:application didFinishLaunchingWithOptions:launchOptionsWithURL];
}
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
return [self bundleURL];
}
- (NSURL *)bundleURL
{
#if DEBUG
return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"];
#else
return [[NSBundle mainBundle] URLForResource:@"principal" withExtension:@"jsbundle"];
#endif
}
// Linking API
- (BOOL)utility:(UIApplication *)utility openURL:(NSURL *)url choices:(NSDictionary *)choices [RCTLinkingManager application:application openURL:url options:options];
// Common Hyperlinks
- (BOOL)utility:(UIApplication *)utility continueUserActivity:(nonnull NSUserActivity *)userActivity restorationHandler:(nonnull void (^)(NSArray> * _Nullable))restorationHandler
//-- ABC - iOS Set up Step 6: Implement this delegate to obtain and set the push token
// Explicitly outline distant notification delegates to make sure compatibility with some third-party libraries
- (void)utility:(UIApplication *)utility didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
if (useNativeImplementation) {
// iOS Set up Step 7: set the push token to Klaviyo SDK
// Exclude if dealing with push tokens from react native layer
[PushNotificationsHelper setPushTokenWithToken:deviceToken];
} else {
// Present token to cross-platform push library, e.g. firebase
}
if (isDebug) {
NSString *token = [self stringFromDeviceToken:deviceToken];
NSLog(@"System Token: %@", token);
}
return [super application:application didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
}
//-- ABC - iOS Set up Step 8: [Optional] Implement this if registering with APNs fails
// Explicitly outline distant notification delegates to make sure compatibility with some third-party libraries
- (void)utility:(UIApplication *)utility didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
if (isDebug) {
NSLog(@"Did not register for distant notifications: %@", error);
}
return [super application:application didFailToRegisterForRemoteNotificationsWithError:error];
}
//-- ABC - iOS Set up Step 9: Implement the delegate didReceiveNotificationResponse to response to person actions (tapping on push) push notifications
// when the app is within the background
// NOTE: this delegate will NOT be known as if iOS Set up Step 2 is just not carried out.
- (void)userNotificationCenter:(UNUserNotificationCenter *)heart didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)())completionHandler {
// iOS Set up Step 10: name `handleReceivingPushWithResponse` methodology and go within the beneath arguments.
// Observe that handleReceivingPushWithResponse calls our SDK and is one thing that needs to be applied in your app as properly.
// Additional, if you wish to intercept urls as a substitute of them being routed to the system and system calling `utility:openURL:choices:` you may implement the `deepLinkHandler` beneath
[PushNotificationsHelper handleReceivingPushWithResponse:response completionHandler:completionHandler deepLinkHandler:^(NSURL * _Nonnull url) {
NSLog(@"URL is %@", url);
[RCTLinkingManager application:UIApplication.sharedApplication openURL: url options: @{}];
}];
// iOS Set up Step 9a: replace the app rely to present badge quantity - 1. It's also possible to set this to 0 for those who
// now not need the badge to indicate.
[PushNotificationsHelper updateBadgeCount: [UIApplication sharedApplication].applicationIconBadgeNumber - 1];
if (isDebug) {
UIAlertController *alert = [UIAlertController
alertControllerWithTitle:@"Push Notification"
message:@"handled background notifications"
preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction
actionWithTitle:@"OK"
style:UIAlertActionStyleDefault
handler:nil]];
[self.window.rootViewController presentViewController:alert animated:YES completion:nil];
}
}
//-- ABC - iOS Set up Step 11: Implement the delegate willPresentNotification to deal with push notifications when the app is within the foreground
// NOTE: this delegate will NOT be known as if iOS Set up Step 2 is just not carried out.
- (void)userNotificationCenter:(UNUserNotificationCenter *)heart
willPresentNotification:(UNNotification *)notification
withCompletionHandler:(void (^)(UNNotificationPresentationOptions choices))completionHandler {
if (isDebug) {
NSDictionary *userInfo = notification.request.content material.userInfo;
// Deal with the push notification payload as wanted
NSLog(@"Obtained Push Notification: %@", userInfo);
// Instance: Show an alert with the notification message
NSString *message = userInfo[@"aps"][@"alert"][@"body"];
UIAlertController *alert = [UIAlertController
alertControllerWithTitle:@"Push Notification"
message:message
preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil]];
[self.window.rootViewController presentViewController:alert animated:YES completion:nil];
}
// iOS Set up Step 12: name the completion handler with presentation choices right here, reminiscent of exhibiting a banner or taking part in a sound.
completionHandler(UNNotificationPresentationOptionAlert | UNNotificationPresentationOptionBadge | UNNotificationPresentationOptionSound);
}
//-- ABC - iOS Set up Step 13: Implement this methodology to obtain deep hyperlink. There are some addition setup steps wanted as talked about within the readme right here -
// https://github.com/klaviyo/klaviyo-swift-sdk?tab=readme-ov-file#deep-linking
// Calling `RCTLinkingManager` is required to your react native listeners to be known as
- (BOOL)utility:(UIApplication *)app openURL:(NSURL *)url choices:(NSDictionary *)choices {
return [RCTLinkingManager application:app openURL:url options:options];
}
//-- ABC - iOS Set up Step 14: if you wish to reset the app badge rely every time the app turns into lively implement this
// delegate methodology and set the badge rely to 0. Observe that this may occasionally typically imply that the person would miss the
// notification.
- (void)applicationDidBecomeActive:(UIApplication *)utility {
[PushNotificationsHelper updateBadgeCount:0];
}
//-- ABC - iOS Set up Step 16: name this methodology from `utility:didFinishLaunchingWithOptions:` earlier than calling the tremendous class methodology with
// the launch arguments. This can be a workaround for a react concern the place if the app is terminated the deep hyperlink is not despatched to the react native layer
// when it's coming from a distant notification.
// https://github.com/fb/react-native/points/32350
- (NSMutableDictionary *)getLaunchOptionsWithURL:(NSDictionary * _Nullable)launchOptions {
NSMutableDictionary *launchOptionsWithURL = [NSMutableDictionary dictionaryWithDictionary:launchOptions];
if (launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey]) {
NSDictionary *remoteNotification = launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey];
if (remoteNotification[@"url"]) {
NSString *initialURL = remoteNotification[@"url"];
if (!launchOptions[UIApplicationLaunchOptionsURLKey]) {
launchOptionsWithURL[UIApplicationLaunchOptionsURLKey] = [NSURL URLWithString:initialURL];
}
}
}
return launchOptionsWithURL;
}
//-- ABC
- (NSString *)stringFromDeviceToken:(NSData *)deviceToken {
const unsigned char *tokenBytes = (const unsigned char *)[deviceToken bytes];
NSMutableString *token = [NSMutableString stringWithCapacity:([deviceToken length] * 2)];
for (NSUInteger i = 0; i < [deviceToken length]; i++) {
[token appendFormat:@"%02x", tokenBytes[i]];
}
return token;
}
// Explicitly outline distant notification delegates to make sure compatibility with some third-party libraries
- (void)utility:(UIApplication *)utility didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
return [super application:application didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
}
@finish
Podfile:
use_modular_headers!
require File.be a part of(File.dirname(`node --print "require.resolve('expo/bundle.json')"`), "scripts/autolinking")
require File.be a part of(File.dirname(`node --print "require.resolve('react-native/bundle.json')"`), "scripts/react_native_pods")
require 'json'
podfile_properties = JSON.parse(File.learn(File.be a part of(__dir__, 'Podfile.properties.json'))) rescue {}
ENV['RCT_NEW_ARCH_ENABLED'] = podfile_properties['newArchEnabled'] == 'true' ? '1' : '0'
ENV['EX_DEV_CLIENT_NETWORK_INSPECTOR'] = podfile_properties['EX_DEV_CLIENT_NETWORK_INSPECTOR']
use_autolinking_method_symbol = ('use' + '_native' + '_modules!').to_sym
origin_autolinking_method = self.methodology(use_autolinking_method_symbol)
self.define_singleton_method(use_autolinking_method_symbol) do |*args|
if ENV['EXPO_UNSTABLE_CORE_AUTOLINKING'] == '1'
Pod::UI.places('Utilizing expo-modules-autolinking as core autolinking supply'.inexperienced)
config_command = [
'node',
'--no-warnings',
'--eval',
'require(require.resolve('expo-modules-autolinking', { paths: [require.resolve('expo/package.json')] }))(course of.argv.slice(1))',
'react-native-config',
'--json',
'--platform',
'ios'
]
origin_autolinking_method.name(config_command)
else
origin_autolinking_method.name()
finish
finish
platform :ios, podfile_properties['ios.deploymentTarget'] || '13.4'
set up! 'cocoapods',
:deterministic_uuids => false
prepare_react_native_project!
goal 'Anadey' do
use_expo_modules!
config = use_native_modules!
use_frameworks! :linkage => podfile_properties['ios.useFrameworks'].to_sym if podfile_properties['ios.useFrameworks']
use_frameworks! :linkage => ENV['USE_FRAMEWORKS'].to_sym if ENV['USE_FRAMEWORKS']
use_react_native!(
:path => config[:reactNativePath],
:hermes_enabled => podfile_properties['expo.jsEngine'] == nil || podfile_properties['expo.jsEngine'] == 'hermes',
# An absolute path to your utility root.
:app_path => "#{Pod::Config.occasion.installation_root}/..",
:privacy_file_aggregation_enabled => podfile_properties['apple.privacyManifestAggregationEnabled'] != 'false',
)
post_install do |installer|
react_native_post_install(
installer,
config[:reactNativePath],
:mac_catalyst_enabled => false,
:ccache_enabled => podfile_properties['apple.ccacheEnabled'] == 'true',
)
# That is needed for Xcode 14, as a result of it indicators useful resource bundles by default
# when constructing for units.
installer.target_installation_results.pod_target_installation_results
.every do |pod_name, target_installation_result|
target_installation_result.resource_bundle_targets.every do |resource_bundle_target|
resource_bundle_target.build_configurations.every do |config|
config.build_settings['CODE_SIGNING_ALLOWED'] = 'NO'
finish
finish
finish
finish
post_integrate do |installer|
start
expo_patch_react_imports!(installer)
rescue => e
Pod::UI.warn e
finish
finish
finish
# goal 'AnadeyExtension' do
# use_frameworks! :linkage => :static
# pod 'KlaviyoSwiftExtension'
# finish
Podfile.lock: codeshare hyperlink
( I pasted in CodeShare as a result of the physique size (66k) went above Stackoverflow’s restrict of 30k characters)
I’ve cleared the Derived Knowledge
folder additionally.
Here’s a record of errors that I discovered when opened Xcode: