braze-inc / braze-react-native-sdk

Public repo for the Braze React Native SDK
https://www.braze.com
Other
64 stars 82 forks source link

[Bug]: new v2+ iOS installation raises concerns #196

Closed Minishlink closed 1 year ago

Minishlink commented 1 year ago

Which Platforms?

iOS

Which React Native Version?

0.70

Which @braze/react-native-sdk SDK version?

2.0.0 - 3.0.0

Description

Hello,

This is more a regression from v1 rather than a bug. The user here is not the end user but the developer.

Currently, the recommended way of installing Braze in v2+ suggests assigning Braze as delegate of the React Bridge.

This raises problems:

Fortunately:

I wonder whether this is simply an error when documenting the new Swift SDK.

alzalabany commented 1 year ago

same issue here; spent almost 4 days debuging tons of issues raised from assignment of delegate to react bridge.

react-native-reanimated breaks as it expects the delegate to be an instance of UIResponder. react-native-firebase also broke

finally, I got push notifications, deep links to work; in-app messaging and content-cards not so much success

info:i use React native 0.71.4 & latest version here 3.0.0;

hokstuff commented 1 year ago

Hi all,

Thanks for raising this concern! We have filed a ticket internally to investigate how to refactor and improve the integration to support the use cases described and to update our public docs with the findings. One thing to note (if applicable for your situation) is that the Braze React Native SDK does not yet officially support the New Architecture - this is one of our next items prioritized in our roadmap.

In the meantime, if you figure out any workarounds or have specific suggestions on how to improve the iOS bridge integration, feel free to post on this thread.

diego-paired commented 1 year ago

We are experiencing the same problem, this is unrelated to the new architecture. Renimated, which is a very popular library, is incompatible with how the Bridge is initialised currently.

 ERROR  [Reanimated] Couldn't determine the version of the native part of Reanimated. Did you forget to re-build the app after upgrading react-native-reanimated? If you use Expo Go, you must use the exact version which is bundled into Expo SDK.
 ERROR  TypeError: Cannot read property 'installCoreFunctions' of undefined, js engine: hermes

@Minishlink what is the old installation method? is it a workaround or simply a suggestion to downgrade? thanks

Minishlink commented 1 year ago

Currently the Braze SDK doesn't make anything of the fact that it is a delegate of RCTBridge, it's just installation annoyance ;) So you can simply skip this step.


@implementation AppDelegate

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

  NSDictionary *info = [[NSBundle mainBundle] infoDictionary];
  NSString *brazeAPIKey = [info objectForKey:@"BrazeAPIKey"];
  NSAssert(brazeAPIKey != nil, @"No Braze API key");
  BRZConfiguration *configuration = [[BRZConfiguration alloc] initWithApiKey:brazeAPIKey
      endpoint:@"sdk.fra-01.braze.eu"];
  Braze *braze = [BrazeReactBridge initBraze:configuration];
  braze.inAppMessagePresenter = [[BrazeInAppMessageUI alloc] init];
  BRZGIFViewProvider.shared = [BRZGIFViewProvider sdWebImage];
  AppDelegate.braze = braze;
  [[BrazeReactUtils sharedInstance] populateInitialUrlFromLaunchOptions:launchOptions];

  [UNUserNotificationCenter currentNotificationCenter].delegate = self;
  [[UNUserNotificationCenter currentNotificationCenter] setNotificationCategories:BRZNotifications.categories];

  NSDictionary *pushDictionary = launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey];
  BOOL launchedFromBrazeInternalPush = pushDictionary && [BRZNotifications isInternalNotification: pushDictionary];
  NSMutableDictionary *appProperties = [NSMutableDictionary dictionaryWithDictionary:[RNFBMessagingModule addCustomPropsToUserProps:nil withLaunchOptions:launchOptions]];
  if (launchedFromBrazeInternalPush && [UIApplication sharedApplication].applicationState == UIApplicationStateBackground) {
    appProperties[@"isHeadless"] = @([RCTConvert BOOL:@(YES)]);
  }

  RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];

  [appProperties addEntriesFromDictionary: [self prepareInitialProps]];

  UIView *rootView = RCTAppSetupDefaultRootView(bridge, @"XXX", appProperties);

  ....
}

- (void) application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
  [AppDelegate.braze.notifications registerDeviceToken:deviceToken];
}

- (void) application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
  (void)[AppDelegate.braze.notifications handleBackgroundNotificationWithUserInfo:userInfo
                                                             fetchCompletionHandler:completionHandler];
}

- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler {
  [[BrazeReactUtils sharedInstance] populateInitialUrlForCategories:response.notification.request.content.userInfo];
  (void)[AppDelegate.braze.notifications handleUserNotificationWithResponse:response
                                                      withCompletionHandler:completionHandler];
}

- (void)userNotificationCenter:(UNUserNotificationCenter *)center
       willPresentNotification:(UNNotification *)notification
         withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler {
  if (@available(iOS 14.0, *)) {
    completionHandler(UNNotificationPresentationOptionList | UNNotificationPresentationOptionBanner);
  } else {
    completionHandler(UNNotificationPresentationOptionAlert);
  }
}

#pragma mark - Braze

static Braze *_braze = nil;

+ (Braze *)braze {
  return _braze;
}

+ (void)setBraze:(Braze *)braze {
  _braze = braze;
}
// AppDelegate.h

#import <React/RCTBridgeDelegate.h>
#import <UserNotifications/UserNotifications.h>
#import <UIKit/UIKit.h>
#import <BrazeKit/BrazeKit-Swift.h>

@interface AppDelegate : UIResponder <UIApplicationDelegate, RCTBridgeDelegate, UNUserNotificationCenterDelegate>

@property (nonatomic, strong) UIWindow *window;

+ (Braze *)braze;

@end
alzalabany commented 1 year ago

for me, i also skipped the delegate step; it's working now with reanimated, firebase and reactnative 0.71.4 not sure if there will be any side effects; but so far everything seems okay.

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

@interface AppDelegate : RCTAppDelegate <UNUserNotificationCenterDelegate>
@end

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  self.moduleName = appName;
  // inject isHeadless Prop
  self.initialProps = [RNFBMessagingModule addCustomPropsToUserProps:nil withLaunchOptions:launchOptions];

  // bootstrap Firebase using Firebase.json config
  [FIRApp configure];

  // change background
  self.window.rootViewController.view.backgroundColor = [UIColor blackColor];

  // Setup Braze
  BRZConfiguration *configuration = [[BRZConfiguration alloc] initWithApiKey:apiKey endpoint:endpoint];
  configuration.triggerMinimumTimeInterval = 1;
  configuration.logger.level = BRZLoggerLevelDebug;
  Braze *braze = [BrazeReactBridge initBraze:configuration];
  AppDelegate.braze = braze;

  [self registerForPushNotifications];
  [[BrazeReactUtils sharedInstance] populateInitialUrlFromLaunchOptions:launchOptions];

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

#pragma mark - Push Notifications

- (void)registerForPushNotifications {
  if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_9_x_Max) {
    UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
    center.delegate = self;
    [center setNotificationCategories:BRZNotifications.categories];
    [[UIApplication sharedApplication] registerForRemoteNotifications];
  }
}

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
  (void)[AppDelegate.braze.notifications handleBackgroundNotificationWithUserInfo:userInfo
                                         fetchCompletionHandler:completionHandler];
}

- (void)userNotificationCenter:(UNUserNotificationCenter *)center
  didReceiveNotificationResponse:(UNNotificationResponse *)response
         withCompletionHandler:(void (^)(void))completionHandler {
  [[BrazeReactUtils sharedInstance] populateInitialUrlForCategories:response.notification.request.content.userInfo];
  (void)[AppDelegate.braze.notifications handleUserNotificationWithResponse:response
                                                      withCompletionHandler:completionHandler];
}

- (void)userNotificationCenter:(UNUserNotificationCenter *)center
       willPresentNotification:(UNNotification *)notification
         withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler {
  completionHandler(UNNotificationPresentationOptionList | UNNotificationPresentationOptionBanner);
}

- (void)application:(UIApplication *)application
  didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
  [FIRMessaging messaging].APNSToken = deviceToken;
  [AppDelegate.braze.notifications registerDeviceToken:deviceToken];
}

- (void)messaging:(FIRMessaging *)messaging didReceiveRegistrationToken:(NSString *)fcmToken {
    NSLog(@"FCM registration Renewed token: %@", fcmToken);
    NSDictionary *dataDict = [NSDictionary dictionaryWithObject:fcmToken forKey:@"token"];
    [[NSNotificationCenter defaultCenter] postNotificationName:
     @"FCMToken" object:nil userInfo:dataDict];
    // If necessary send token to application server.
    // Note: This callback is fired at each app startup and whenever a new token is generated.
}
CoryWritesCode commented 1 year ago

@alzalabany are you able to get content cards to show with your setup?

CoryWritesCode commented 1 year ago

Any progress on this @hokstuff?

@Minishlink implementing your solution I still get Use of undeclared identifier 'BrazeInAppMessageUI' and I can't seem to find the correct import for that variable

Minishlink commented 1 year ago

Use the following import #import <BrazeUI/BrazeUI-Swift.h> (the BrazeInAppMessageUI part is only needed if you want to support in app messages with Braze standard UI)

Minishlink commented 1 year ago

@alzalabany are you able to get content cards to show with your setup?

Content cards support is very buggy right now, use the following patch https://github.com/braze-inc/braze-react-native-sdk/issues/201#issuecomment-1481545388 You will need to setup a Braze.Events.CONTENT_CARDS_UPDATED listener that sends you the cards as payload in order to have always up-to-date content cards when anything changes on the native side

CoryWritesCode commented 1 year ago

@Minishlink looks like #import <BrazeUI/BrazeUI-Swift.h> doesn't come with the rn sdk v3 image

I'd prefer to just let braze do it's thing. It's working fine on android for me but iOS isn't getting the in app message test I'm running right now

hokstuff commented 1 year ago

Hi @Minishlink @alzalabany and @CoryWritesCode,

Below is the diff of the proposed changes to resolve the issues on these two issues on the thread:

  1. Updates the sample app / recommended integration to avoid overwriting the React bridge's delegate.
  2. Sets the In-app message UI without an additional integration step in the AppDelegate.
    • This will occur automatically instead of needing to call subscribeToInAppMessage.

We are currently validating these changes and are aiming to release them in the near future. If you have any comments or if you run into issues when validating these changes in your apps, feel free to post on this thread prior to the next release.

diff --git a/public/BrazeProject/ios/BrazeProject/AppDelegate.mm b/public/BrazeProject/ios/BrazeProject/AppDelegate.mm
index 8ee2381..52dcc5b 100644
--- a/public/BrazeProject/ios/BrazeProject/AppDelegate.mm
+++ b/public/BrazeProject/ios/BrazeProject/AppDelegate.mm
@@ -24,12 +24,12 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(
   self.initialProps = @{};

   // Setup Braze bridge
-  id<RCTBridgeDelegate> moduleInitializer = [[BrazeReactBridge alloc] init];
-  RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:moduleInitializer
-                                            launchOptions:launchOptions];
-  RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
-                                                   moduleName:@"BrazeProject"
-                                            initialProperties:nil];
+  NSURL *jsCodeLocation =
+      [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios"];
+  RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
+                                                      moduleName:self.moduleName
+                                               initialProperties:self.initialProps
+                                                   launchOptions:launchOptions];
   self.bridge = rootView.bridge;

   // Configure views in the application
diff --git a/public/iOS/BrazeReactBridge/BrazeReactBridge/BrazeReactBridge.h b/public/iOS/BrazeReactBridge/BrazeReactBridge/BrazeReactBridge.h
index 266e83a..32dd660 100644
--- a/public/iOS/BrazeReactBridge/BrazeReactBridge/BrazeReactBridge.h
+++ b/public/iOS/BrazeReactBridge/BrazeReactBridge/BrazeReactBridge.h
@@ -4,7 +4,7 @@

 #import <BrazeKit/BrazeKit-Swift.h>

-@interface BrazeReactBridge : RCTEventEmitter <RCTBridgeModule, RCTBridgeDelegate>
+@interface BrazeReactBridge : RCTEventEmitter <RCTBridgeModule>

 /// Intializes the Braze instance based on a configuration. This same instance is also used by the Braze bridge.
 /// - Parameters:
diff --git a/public/iOS/BrazeReactBridge/BrazeReactBridge/BrazeReactBridge.m b/public/iOS/BrazeReactBridge/BrazeReactBridge/BrazeReactBridge.m
index c8fb5db..07908de 100644
--- a/public/iOS/BrazeReactBridge/BrazeReactBridge/BrazeReactBridge.m
+++ b/public/iOS/BrazeReactBridge/BrazeReactBridge/BrazeReactBridge.m
@@ -74,6 +74,10 @@ - (void)startObserving {
     RCTLogInfo(@"Received News Feed cards via subscription of length: %lu", [cards count]);
     [self sendEventWithName:kNewsFeedCardsUpdatedEvent body:nil];
   }];
+
+  // Add default in-app message UI
+  BrazeInAppMessageUI *inAppMessageUI = [[BrazeInAppMessageUI alloc] init];
+  braze.inAppMessagePresenter = inAppMessageUI;
 }

 - (void)stopObserving {
@@ -754,12 +758,10 @@ - (void)braze:(Braze * _Nonnull)braze
 RCT_EXPORT_METHOD(subscribeToInAppMessage:(BOOL)useBrazeUI)
 {
   useBrazeUIForInAppMessages = useBrazeUI;
-
-  BrazeInAppMessageUI *inAppMessageUI = [[BrazeInAppMessageUI alloc] init];
-  inAppMessageUI.delegate = self;
-  braze.inAppMessagePresenter = inAppMessageUI;
+  ((BrazeInAppMessageUI *)braze.inAppMessagePresenter).delegate = self;
 }

+/// `BrazeInAppMessageUIDelegate` method
 - (enum BRZInAppMessageUIDisplayChoice)inAppMessage:(BrazeInAppMessageUI *)ui
                             displayChoiceForMessage:(BRZInAppMessageRaw *)message {
   NSData *inAppMessageData = [message json];
@@ -819,12 +821,6 @@ - (BRZInAppMessageRaw *)getInAppMessageFromString:(NSString *)inAppMessageJSONSt
   return nil;
 }

-#pragma mark - RCTBridgeDelegate protocol
-
-- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge {
-  return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"];
-}
-
 RCT_EXPORT_MODULE();

 @end

Note that our next release will also include fixes / requests from a few other open issues:

Thanks!

artyorsh commented 1 year ago

@hokstuff

This will occur automatically instead of needing to call subscribeToInAppMessage.

Since we are in context of react-native package, wouldn't it be better to actually have subscribeToInAppMessage instead of requiring native code to assign BrazeInAppMessageUI? This is what SDK does right now as far as I see. Moreover, the suggested approach requires integration of delegate once you decide to go with custom UI for in-app messages.

Also to post another problem that we face: With v3, the SDK comes with a breaking change of storing in-app message images to local files (and providing file://-like uri's to JS). While it could be an optimization for non-custom IAM integration, it requires an additional compatibility layer for apps using custom UI. Moreover, it's not compatible to Android, where the image comes with https:// path - so, again, requires writing platform-specific code, which is not really developer friendly in context of package for react-native. Can you please add a flag to control this? Or maybe document the case and provide an example of rendering images with file:// path?

Minishlink commented 1 year ago

Since we are in context of react-native package, wouldn't it be better to actually have subscribeToInAppMessage instead of requiring native code to assign BrazeInAppMessageUI? This is what SDK does right now as far as I see. Moreover, the suggested approach requires integration of delegate once you decide to go with custom UI for in-app messages.

Actually I think it makes more sense for two reasons:

An optional ios_enableIAMBrazeUI could be added though, for when the user is not confident in native code.

hokstuff commented 1 year ago

Since we are in context of react-native package, wouldn't it be better to actually have subscribeToInAppMessage instead of requiring native code to assign BrazeInAppMessageUI? This is what SDK does right now as far as I see. Moreover, the suggested approach requires integration of delegate once you decide to go with custom UI for in-app messages.

In the proposed change, it removes any need for iOS-native code to add BrazeInAppMessageUI since that would be executed in startObserving after the bridge is instantiated, and the BrazeBridge already implements the delegate method. This change would also match the behavior of subscribeToInAppMessages more closely to Android, where its only jobs are:

  1. Hook up a listener for in-app messages that forwards the data to the JS layer.
    • On iOS, it is done via a delegate method (see ((BrazeInAppMessageUI *)braze.inAppMessagePresenter).delegate = self; in the patch above), while Android does it via adding a listener
  2. Use the boolean useBrazeUI to determine whether or not to display via the default Braze UI

Also to post another problem that we face: With v3, the SDK comes with a breaking change of storing in-app message images to local files (and providing file://-like uri's to JS). While it could be an optimization for non-custom IAM integration, it requires an additional compatibility layer for apps using custom UI. Moreover, it's not compatible to Android, where the image comes with https:// path - so, again, requires writing platform-specific code, which is not really developer friendly in context of package for react-native. Can you please add a flag to control this? Or maybe document the case and provide an example of rendering images with file:// path?

@artyorsh Can you contact the Support team with more information on this issue so we can fully understand the current behavior, current workarounds, as well as any relevant context as to how to address the concern? We will need to game plan on whether to solve it in the native layer vs "wrapper" layer.

An optional ios_enableIAMBrazeUI could be added though, for when the user is not confident in native code.

Internally, we strive to make a consistent interface across our several Braze "wrappers" (React Native, Flutter, Unity, etc) and are trying to limit adhoc config options that may lead to bugs on a single platform. The hope of the proposed solution above is to simplify the configuration to lead to fewer integration permutations - but we will note this suggestion internally!

hokstuff commented 1 year ago

Hi @Minishlink @alzalabany @artyorsh and @CoryWritesCode,

We have released SDK version 4.0.0 which makes updates in the sample app as well as the iOS bridge to address the concern of overwriting the React bridge delegate. We will also update our public docs to reflect this updated recommended integration method on the iOS native layer.

If you continue to run into issues on this same topic, feel free to reopen this thread or else create a new thread if it is regarding a different issue.

Thank you all for your patience!

Minishlink commented 1 year ago

Hello @hokstuff, thank you for reacting quickly to these issues :) 👏

cam-shaw commented 1 year ago

@hokstuff I believe this might still be an issue in 4.1.0. Running 4.1.0 of this library, I still had to add the subscribeToInAppMessage listener for the IAM content to show.

Braze.subscribeToInAppMessage(true, () => {});

In Xcode, I had a breakpoint on Line 84 in BrazeReactBridge BrazeInAppMessageUI *inAppMessageUI = [[BrazeInAppMessageUI alloc] init]; and noticed it wasn't triggered until I had added the listener above.

Once the listener was added, IAM were showing up and the breakpoint was triggered.

hokstuff commented 1 year ago

Hi @cam-shaw,

It sounds like the issue you are facing is different than the thread here. Can you contact support@braze.com with more information on your integration, including the relevant parts of your AppDelegate (didFinishLaunching and any other Braze-related code)? Also, can you provide more info on your integration, such as if you are using custom vs default UI?

Thanks!

sregg commented 1 year ago

In-App Messages also stopped working for us in 4.1.0 on iOS after migrating from the AppBoy SDK. They're working fine on Android.

jerielng commented 1 year ago

Hi @sregg - could you provide some additional details around your implementation? Are you able to receive in-app messages on iOS after following the steps described here by setting the parameter to true?

sregg commented 1 year ago

We don't have that listener as the docs explains it should work without

image

But that reminds me that we need to track IAM impressions for analytics purposes so I'll add that and see if that helps. Also, is that listener different than

 Braze.addListener(Braze.Events.IN_APP_MESSAGE_RECEIVED, ...)

?

sregg commented 1 year ago

Yup it worked after adding:

Braze.subscribeToInAppMessage(true, () => {});
sregg commented 1 year ago

Also the callbacks in Braze.subscribeToInAppMessage() and Braze.addListener(Braze.Events.IN_APP_MESSAGE_RECEIVED are never triggered for some reason. Even when the in-app message is clearly shown in the app.

Here's our code:

import Braze from '@braze/react-native-sdk';
import { useCallback } from 'react';

import { Events, useReporting } from '~/reporting';

export const useInAppMessages = () => {
  const { track } = useReporting();
  const trackInAppMessages = useCallback(
    () =>
      Braze.subscribeToInAppMessage(true, (event: { inAppMessage: string }) => {
        const inAppMessage = new Braze.BrazeInAppMessage(event.inAppMessage);

        track({
          eventName: Events.IN_APP_MESSAGE_RECEIVED,
          kind: 'analytics',
          payload: {
            type: inAppMessage.messageType,
            message: inAppMessage.message,
            header: inAppMessage.header,
          },
        });
      }),
    [track]
  );

  return { trackInAppMessages };
};

then in our RootNavigator.tsx

  const { trackInAppMessages } = useInAppMessages();
  useEffect(() => {
    const inAppMessagesTrackingSub = trackInAppMessages();
    return inAppMessagesTrackingSub?.remove;
  }, [trackInAppMessages]);

a console.log() above const inAppMessage = ... won't be shown when receiving and showing an in-app message in the app.

hokstuff commented 1 year ago

Hi @sregg,

Would you be able to contact support@braze.com with this thread and attach the info above? It sounds like a tangential but separate issue than this closed post, and we'd like to keep the conversation on its own thread to cater towards your issue specifically.

From the public docs, the phrase

Native in-app messages display automatically on Android and iOS when using React Native.

refers to being able to present in-app messages using the out-of-the-box UI, with no customization at all. To add a custom UI or custom logic for metrics, you will need to use Braze.subscribeToInAppMessage as you noted above, alongside any other possible customizations.

Regarding your code snippets here, please contact our Support team with steps to repro and verbose logs so we can continue the investigation.

Thank you!

sregg commented 1 year ago

That's right, we're not using custom UI. In fact, if we just add

Braze.subscribeToInAppMessage(true, () => {});

the in-app messages appear, whereas they don't if we don't add that line. I'll contact support.

cam-shaw commented 1 year ago

Same issue and fix as I had. @hokstuff our team contacted Support about a separate issue and was told to follow the Github thread as it was with the dev team. Can I just confirm with you that contact Support is the best way to resolve this issue? I'd prefer not going in circles 😅

hokstuff commented 1 year ago

Hi @cam-shaw,

Can you post the Support case number so I could follow up on that thread? Going through Support instead of Github allows us to keep all the relevant info in one place, and that way you can attach files, code snippets, etc easier to associate in one place. For instance, this thread has multiple conversations happening at once for different host apps, so responses can get mixed up.

In addition to your case number, in your response to Support, can you include:

  1. Verbose logs in the problematic setup. (Optional to include with the setup that functions as expected)
  2. Adding additional logging that prints out braze.inAppMessagePresenter in the iOS layer of your application
    • Feel free to make local changes in the bridge layer, e.g. here or here, as well as in your AppDelegate code.
  3. All code around your in-app message integration (e.g. custom UI), and your AppDelegate code.
  4. If you can, feel free to use our sample app and attempt to repro the issue, since this will help diagnose the issue. Thus far, we have not been able to repro the behavior described above after removing the call to subscribeToInAppMessage and using a vanilla integration in our sample app with default UI

Thanks, Daniel