Leanplum / Leanplum-iOS-SDK

Leanplum's integrated solution delivers meaningful engagement across messaging and the in-app experience.
https://www.leanplum.com
Apache License 2.0
73 stars 58 forks source link

Alert views presented on wrong view controller #7

Closed marcgug closed 7 years ago

marcgug commented 9 years ago

Here is my situation:

1) I have an alert configured in the leanplum messaging dashboard to appear when State "ViewController2" is triggered. I also set verbose debug logging and trackAllAppScreens as follows:

[Leanplum setVerboseLoggingInDevelopmentMode:YES];
[Leanplum trackAllAppScreens];

2) In my app, I present ViewController2 with the following code:

UIStoryboard *SB = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
ViewController2 *vc2 = [SB instantiateViewControllerWithIdentifier:@"VC2"];
[self preventViewController2: vc2 animated:YES completion:nil];

3) When I load ViewController2, I can see in the debug logs that Leanplum is attempting to display the alert I configured in step 1. However, the alert never appears, and I see this message in the xcode logs: Warning: Attempt to present <UIAlertController: 0x7fbffa67c180> on <ViewController: 0x7fbffa4536a0> whose view is not in the window hierarchy!

So, it seems like Leanplum is attempting to present the UIAlertView on the rootViewController, which is no longer visible, instead of the current view controller that is being displayed.

Additionally, if I change the message type from "Alert" to "Center popup" in Leanplum, then it appears as expected.

I'm happy to provide more information or a sample project if that would help.

afirst commented 9 years ago

We'll fix this in the next release. In the meantime, there is a workaround. First, add LPMessageTemplates.h/m to your project. These files are available if you download the SDK from Help > Setup. You'll need to initialize these templates by calling [LPMessageTemplates sharedTemplates] before calling [Leanplum start]. Then, in LPMessageTemplates.m, add this method:

+ (UIViewController *)visibleViewController
{
    UIViewController *root = [UIApplication sharedApplication].keyWindow.rootViewController;
    if (root.presentedViewController) {
        return root.presentedViewController;
    }
    return root;
}

And replace both occurrences of:

[[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:alert animated:YES completion:nil];

with:

[[LPMessageTemplatesClass visibleViewController] presentViewController:alert animated:YES completion:nil];
akimdeliverydotcom commented 9 years ago

Do you know when the next release will happen? We're trying to determine if we should put in this fix now or if we should wait. Also, when you say next release are you referring to a new SDK?

afirst commented 9 years ago

I would say within a week. The fix was tested in different scenarios, but if you have time to test it in your app, that would make sure we covered your specific use case.

akimdeliverydotcom commented 9 years ago

Thanks for the update. We'll run tests in our app with the fix you recommended and will let you know how it turns out.

marcgug commented 9 years ago

Hi @afirst,

I tried your workaround, and it almost works. However, sometimes we have multiple view controllers presented on the rootViewController, so the following works better for us for the visibleViewController method:

+ (UIViewController *)visibleViewController
{
    UIViewController *topController = [UIApplication sharedApplication].keyWindow.rootViewController;
    while (topController.presentedViewController) {
        topController = topController.presentedViewController;
    }
    return topController;
}

We are still testing to see if this works in all situations, but so far things are much improved.

afirst commented 9 years ago

Glad you were able to test it and thanks for the feedback! We'll incorporate that change.

alexisoyama commented 7 years ago

Cleaning up the opened issues. I just made a sample app and did not show any error.