View Controller Child B, which would get pushed from the parent A
If we invoke InAppManager.show(message:consume:callback:) from parent A and the user navigates to child B while the InAppDisplayer is building the Iterable message, then we have a state where InAppDisplayer.getViewController() will return child B as the topViewController, which is the correct ViewController, however, the circumstances for every app change and showing a modal would bring a bad UX to the app.
Right now, once we fire an InAppManager.show(message:consume:callback:), it could literally show in any screen, considering limited resources of possible devices, especially when we support emerging markets.
Expected behaviour
I believe that the expected behaviour would be (1) to have the Iterable modal only displaying on the View Controller that fired it or (2) for us to have a way to set the target view controller externally, such as:
Approach (1):
// InAppManager.Swift
func show(message: IterableInAppMessage, consume: Bool = true, callback: ITBURLCallback? = nil) {
ITBInfo()
// get top view controller before any async operation happen
let topViewController = InAppDisplayer.getTopViewController
DispatchQueue.main.async {[weak self] in
self?.showInternal(message: message, consume: consume, callback: callback, topViewController: topViewController)
}
}
Approach (2):
// Let the user decide which view controller is the target one
@objc public protocol IterableInAppManagerProtocol {
...
/// - parameter message: The message to show.
@objc(showMessage:) func show(message: IterableInAppMessage)
/// - parameter message: The message to show.
/// - parameter consume: Set to true to consume the event from the server queue if the message is shown. This should be default.
/// - parameter callback: block of code to execute once the user clicks on a link or button in the in-app notification.
/// Note that this callback is called in addition to calling `IterableCustomActionDelegate` or `IterableUrlDelegate` on the button action.
@objc(showMessage:consume:callbackBlock:) func show(message: IterableInAppMessage, consume: Bool, callback: ITBURLCallback?)
/// - parameter message: The message to show.
/// - parameter consume: Set to true to consume the event from the server queue if the message is shown. This should be default.
/// - parameter targetViewController: The View Controller that will display the in-app notification.
/// - parameter callback: block of code to execute once the user clicks on a link or button in the in-app notification.
/// Note that this callback is called in addition to calling `IterableCustomActionDelegate` or `IterableUrlDelegate` on the button action.
@objc(showMessage:consume:targetViewController:callbackBlock:) func show(message: IterableInAppMessage, consume: Bool, targetViewController: UIViewController?, callback: ITBURLCallback?)
}
**Final Thought**
My team really hopes that in the future Iterable will allow us to have more flexibility in that part of the library as the solution of my team right now is a workaround and could be broken depending on how the library is updated in the future. Cheers.
Problem Imagine we have the following hierarchy:
Parent A
Child B
, which would get pushed from the parent AIf we invoke InAppManager.show(message:consume:callback:) from
parent A
and the user navigates to childB
while the InAppDisplayer is building the Iterable message, then we have a state where InAppDisplayer.getViewController() will returnchild B
as thetopViewController
, which is the correct ViewController, however, the circumstances for every app change and showing a modal would bring a bad UX to the app.Right now, once we fire an InAppManager.show(message:consume:callback:), it could literally show in any screen, considering limited resources of possible devices, especially when we support emerging markets.
Expected behaviour I believe that the expected behaviour would be (1) to have the Iterable modal only displaying on the View Controller that fired it or (2) for us to have a way to set the target view controller externally, such as:
Approach (1):
@objc public protocol IterableInAppManagerProtocol { ... /// - parameter message: The message to show. @objc(showMessage:) func show(message: IterableInAppMessage)
}