Closed aodhol closed 6 years ago
@aodhol Thanks for the feedback. The new BTAppSwitchDelegate.appContextDidReturn
callback is unrelated to the dismissal of possibly presented SFSafariViewController
or SFAuthenticationViewController
. It just implies that the user has returned to your application - this would be useful for updating existing UI or other aspects of your application.
Hierarchy changes should wait until you receive the callback from the driver.
Just curious, what is your intent with displaying an alert before receiving the BTPaypalDriver callback?
@demerino to clarify: I am getting the BTPaypalDriver callback, the problem is that SFAuthenticationViewController has apparently not dismissed by that time if the error is to be believed. I'm trying to show an error message when the shipping or billing addresses are missing....
I'm not sure I understand the issue. In my test on iOS 11 - showing an alert after getting the callback isn't showing that error (in the simulator). Can you help me reproduce the issue?
[driver requestBillingAgreement:checkout completion:^(BTPayPalAccountNonce * _Nullable tokenizedPayPalCheckout, NSError * _Nullable error) {
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"ALERT", nil) message:nil preferredStyle:UIAlertControllerStyleAlert];
[alertController addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"Done", nil) style:UIAlertActionStyleDefault handler:^(__unused UIAlertAction * _Nonnull action) {
NSLog(@"Alert Closed");
}]];
[self presentViewController:alertController animated:YES completion:nil];
}];
@demerino For me, the problem occurs when I do the following (though inconsistently i.e. there's a possible race condition):
let payPalDriver = BTPayPalDriver(apiClient: braintreeClient)
payPalDriver.viewControllerPresentingDelegate = self
payPalDriver.appSwitchDelegate = self
let payPalRequest = BTPayPalRequest(amount: "1.99")
payPalRequest.currencyCode = "GBP"
payPalRequest.isShippingAddressRequired = true
payPalDriver.requestOneTimePayment(payPalRequest) { (tokenizedPayPalAccount, error) -> Void in
// Do stuff.....
// FIXME: the asyncAfter is a workaround for this issue: https://github.com/braintree/braintree_ios/issues/401
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
self.showAlert(title: "Error", message: "Shipping or billing address not specified")
}
return
}
I'd rather not have to dispatchAfter
one second as it seems arbitrary and brittle and from a UX point of view, introducing further delay compounds the poor experience of opening of a Web browser etc.
Could you try to do it several times and keep an eye on the console?
Are you still having issues with this?
@demerino Just tested on 4.16.0 and the problem does occur:
Attempt to present <UIAlertController: 0x116737600> on <SFAuthenticationViewController: 0x1166da600> whose view is not in the window hierarchy!
i have similar issue Warning: Attempt to present <SFAuthenticationViewController: 0x7fcfb15c3400> on <BTDropInController: 0x7fcfb9323780> whose view is not in the window hierarchy!
Any suggestions
@aodhol @bensonbob Got it. Yes the method is called at the correct time but it does not mean that the SFAuthenticationSession view controller has completed the dismissal animation which is probably why you're seeing the error: https://github.com/braintree/braintree_ios/blob/master/BraintreePayPal/BTPayPalDriver.m#L412
The method is called when context has returned to the merchant app to continue processing the PayPal flow.
I haven't tried it myself, but maybe listening on the parent view controller's didAppear
or similar will work?
Have y'all tried @demerino's suggestion?
I haven't tried it myself, but maybe listening on the parent view controller's didAppear or similar will work?
This is probably the same issue we are facing on FB SDK, I opened a ticket for them where I also put a workaround
Closing this now as @demerino has given a good suggestion.
If y'all are still having issues, feel free to comment here.
General information
Issue description
It seems the SFAuthenticationViewController is still in the hierarchy after the delegate method:
BTAppSwitchDelegate.appContextDidReturn
is called.I'm not seeing the UIAlertView I expect to see because:
Warning: Attempt to present <UIAlertController: 0x7b640010f900> on <SFAuthenticationViewController: 0x7b6400104f00> whose view is not in the window hierarchy
Are you sure the
BTAppSwitchDelegate
delegate method above is being called at the appropriate time in theSFSafariViewController
Completion Handler or wherever?