0

I trying to present UIViewController in my React native app from Swift module I am presenting it like this

  let screen = UIApplication.shared.windows.filter {$0.isKeyWindow}.first
  screen?.rootViewController?.present(payController!, animated: true, completion: nil);
  

and I get this error: UIApplication.windows must be used from main thread only

ok I have to add it to my thread

  DispatchQueue.main.async {
    let screen = UIApplication.shared.windows.filter {$0.isKeyWindow}.first
    screen?.rootViewController?.present(payController!, animated: true, completion: nil);
  }

and it works fine when I call this function with small delay

setTimeout(() => {
  showMyWiew();
}, 500);

or delay into swift like this

  DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
    let screen = UIApplication.shared.windows.filter {$0.isKeyWindow}.first
    screen?.rootViewController?.present(payController!, animated: true, completion: nil);
  }

but if I remove the delay then this modal is not shown. But it should be there. and i see this in log in swift which confirms my theory:

[Presentation] Attempt to present <PKAddPaymentPassViewController: 0x103d6b2e0> on <UIViewController: 0x103c25480> (from <UIViewController: 0x103c25480>) which is already presenting <RCTModalHostViewController: 0x10e21df40>.

PKAddPaymentPassViewController is my UIViewController

I don't know how to fix this issue...

UPDATE

Based on first comment I did this

  DispatchQueue.main.async {
    let screen = UIApplication.shared.windows.filter {$0.isKeyWindow}.first
    let controller = screen?.rootViewController?.presentedViewController;
    if controller == nil {
      screen?.rootViewController?.present(payController!, animated: true, completion: nil);
    } else {
      screen?.rootViewController?.presentedViewController?.present(payController!, animated: true, completion: nil)
    }

  }

and the good news is the modal will show up but immediately is close I see the open effect and then close effect ...

SOLUTION

  1. all in the update section
  2. refactoring RN code It turned out There is open another modal before this new. The old modal is not closed before I open the new one ... so I close the old modal faster and then I show new and all is good
Lukáš Šálek
  • 1,265
  • 2
  • 19
  • 38

1 Answers1

0

That is because at that exact moment screen?.rootViewController seems to already present another ViewController (RCTModalHostViewController). A VC that is already presenting some VC can not present yet another VC. What you could do is to call present on the VC that is being presented by the rootViewController at that moment: screen?.rootViewController.presentedViewController?.present(...). (Presenting on a presented ViewController does work. Presenting on a VC that presents another VC does not.)

If you do that you should also make sure that presentedViewController is actually set and not nil. If it is nil you can just call present on rootViewController as you did earlier.

JanMensch
  • 1,720
  • 1
  • 18
  • 27
  • Thank you ... the good news is the modal will show up but immediately is close I see the open effect and then close effect ... check my update... can you help me with this issue also? – Lukáš Šálek Nov 30 '21 at 15:00
  • Then it probably depends on the actual situation you're trying to present. It seems to me that the `presentedViewController` is just about to be dismissed when you call `present`. When the `presentedViewController` gets dismissed it will also dismiss anything that it presents in turn. So that would explain both your initial problem and the new one. Two ways to fix this: 1) find a better place in the code to call `present` Or 2) make sure that the `presentedViewController` does not get dismissed at that moment. I don't know how much influence you have here with react native though... – JanMensch Dec 01 '21 at 08:03
  • i tried to add it on another place but doesn't work... now I am playing with ` `controller?.isModalInPresentation = true` this work ... but I can not use cancel button in modal .... any idea why? – Lukáš Šálek Dec 01 '21 at 15:45
  • If the timing issue is a limitation by the module you're using with react native, I think you'll have to look for a completely different approach of getting the view out. Maybe not use a modal? – JanMensch Dec 02 '21 at 08:01
  • it is `add card to apple wallet` and apple force us to use this modal ... – Lukáš Šálek Dec 02 '21 at 08:19
  • 1
    after some refactoring, it works ... thanks – Lukáš Šálek Dec 02 '21 at 09:47