razorpay / razorpay-pod

:iphone: CocoaPod implementation of Razorpay's Payment SDK. Refer for instructions:
https://docs.razorpay.com/v1/page/ios-integration
MIT License
22 stars 18 forks source link

Attempt to present <UINavigationController> on <HomeTabBarController> whose view is not in the window hierarchy. #38

Closed akashvercetti closed 6 years ago

akashvercetti commented 6 years ago

Xcode 10, iOS 12, Swift 4.2.

After upgrading to the latest Pod, I'm not able to present the Razorpay scene. The console message I get is Warning: Attempt to present <UINavigationController: 0x10527fe00> on <**HomeTabBarController**: 0x104559df0> whose view is not in the window hierarchy!

The reason I'm guessing for this is, the Razorpay scene is presented on the key window's RootViewController , and in many cases like ours, the RootViewController(in this case, TabBarControler) might be so far behind in the hierarchy because of presented controllers on top of it that it would be impossible to present the Razorpay scene.

Could you please look into this edge case?

iThink32 commented 6 years ago

hey @akashvercetti Razorpay first checks if you have a navigation controller , if you do it is pushed on top of everything else it is presented on the topviewcontroller.

iThink32 commented 6 years ago

@akashvercetti this is the standard procedure that is usually followed on iOS so changing it would be difficult , please let me know if there is any other way I can help you.

akashvercetti commented 6 years ago

Just throwing this idea out there, but could you create an additional .open method which accepts a presenting controller parameter and maybe a push/present enum value? This method would allow us present/push razorpay scenes from a viewController of our choice. You can keep the original .open method intact as it is.

rkpradeep20 commented 6 years ago

Hey, I'm facing the same issue. I'm trying to present Razorpay over a navigation controller. But, it's throwing an error. From what I have analyzed, razorpay is trying to present the screen from the RootVC. I guess that's the reason for this issue. There are two scenarios where I see issues arising: One in a container or another when there is no container. Can you change the view controller in the framework with conditions to check if it has a parentViewController(Incase of ContainerVC) if not make it present on the delegate associated VC. That would be a quick fix.

rkpradeep20 commented 6 years ago

I found one more thing helpful. I you are setting the view controller by this method: if var topController = UIApplication.sharedApplication().keyWindow?.rootViewController, Then here is helpful link: https://stackoverflow.com/questions/26667009/get-top-most-uiviewcontroller Getting the topmost view controller if var topController = UIApplication.sharedApplication().keyWindow?.rootViewController { while let presentedViewController = topController.presentedViewController { topController = presentedViewController }

// topController should now be your topmost view controller

}

Then Presenting the razorpay view using topController would work.

I would appreciate a quick fix as the development on the iOS end has stalled because of this issue. We have a deadline and on a time crunch to deliver the app by dussehra.

Thanks, Pradeep.

iThink32 commented 6 years ago

@akashvercetti ok good suggestion but can u give me a few use cases where the current implementation is difficult to handle

iThink32 commented 6 years ago

@rkpradeep20 our ViewController is only presented in case your rootviewcontroller is not a UINavigationController , else it is pushed on to the navigation stack. In response to your link , I can present it on the top most controller but don't you thing it is not a good idea? Ideally a given controller A should present only one screen if required , presenting multiple controllers is usually not a good approach , if you want to display screen A after screen B and so forth a navigation controller is preferred.

Let me know if can help you in any other way.

rkpradeep20 commented 6 years ago

@iThink32 I totally agree with your argument. Let me just give your my current scenario, and what issue I'm facing. My View Hierarchy:

Root View Controller: Initial View Controller UINavigationViewController: Checkout Flow Navigation Stack

Checkout Flow Navigation Stack is presented on top of Initial View Controller to complete buying the product. If as you mentioned, razorpay should be able to push itself onto Checkout Flow Navigation stack, but it is not. Its trying to present a new navigation controller on top of Initial View Controller which is the Root View Controller, and not get pushed onto the Checkout Flow Navigation Stack.

Warning: Attempt to present <UINavigationController: 0x7fb50b806c00> on <Jyothirvaibhava.Initial_ViewController: 0x7fb5076083a0> whose view is not in the window hierarchy!

I did not have any issue with this when I was testing the app on iOS 11 just 3 days back. We were waiting for razorpay framework to be compiled with swift 4.2 and start making the required fixes for iOS 12 before releasing the app. So, can you please check back on your end and let us know.

Thanks, Pradeep.

nikilesh122 commented 6 years ago

ezgif com-video-to-gif

hi iam launchin razor-pay page in navigation controller when launched the razor pay page it comes back to my page but the navigation bar is lost as you can see in the above gif below is another gif

ezgif com-video-to-gif

akashvercetti commented 6 years ago

Pradeep has explained the bug pretty well. Here's my scenario.

RootViewController: TabBarController T. A UINavigationController N is presented over a tab, followed by a ViewController V which is pushed. Now according to the logic described by iThnk32, the razor pay scene should have been pushed. But instead we get the message as the issue title.

The same code used to work in iOS 11 and the older pod.

It is almost certain that the RootViewController is being involved here, as evident by the console message in Xcode.

Please fix this bug on priority.

iThink32 commented 6 years ago

@rkpradeep20 your pictures clearly shows that Razorpay is being pushed on to your nav stack (check the animation or try printing navVC.viewcontrollers), the issue Warning: Attempt to present <UINavigationController: 0x7fb50b806c00> on <Jyothirvaibhava.Initial_ViewController: 0x7fb5076083a0> whose view is not in the window hierarchy! is not because to that

check this link

https://stackoverflow.com/questions/11862883/attempt-to-present-uiviewcontroller-on-uiviewcontroller-whose-view-is-not-in-the

it is because your are calling open before a navigation completes.

iThink32 commented 6 years ago

@akashvercetti I think you should also have a look at the link shared above.

There are multiple reasons for an error message , please have a look.

rkpradeep20 commented 6 years ago

I'm pretty sure @akashvercetti and I made our point and clearly addressed the issue. The link you provided is helpful for people who try to present the View Controller in viewDidLoad method. But the issue we are facing and the solution you are giving us, is in no way relevant.

Thanks for no help.

iThink32 commented 6 years ago

@rkpradeep20 it is occurring because we are checking the type of your rootviewcontroller , in your case it is not a UINavigationController due to which it is getting presented , to get things clear just take a sample app and test it with/without a navigation controller and it will clearly explain what is happening Lets say post this , you still need my help we can have a team viewer session and I can help you out.

rkpradeep20 commented 6 years ago

The sample app is not working its crashing on launch.

The log:

screen shot 2018-09-30 at 4 13 26 pm
rkpradeep20 commented 6 years ago

We should be able to launch the payment screen on any View Controller, not just from root view controller.

iThink32 commented 6 years ago

@rkpradeep20 by sample app I mean create your own sample app and test , yes we can launch the payment screen on any controller , give it a try.

rkpradeep20 commented 6 years ago

I have made a test project as you requested and I'm still facing the issue. Please clone the project from the link below to have a look: https://github.com/rkpradeep20/RazorpayTest

Gif of the screen grab for the above project. image

As mentioned its only looking for the Root View Controller when presenting the Payment Screen. Its not presenting on any other view controller presented.

iThink32 commented 6 years ago

@rkpradeep20 yes that was my point from the beginning if your rootviewcontroller is a uinavigationcontroller it will push else it will present on the rootViewController, I will modify your sample app and show you the two options , can you drop your email id?

rkpradeep20 commented 6 years ago

Sure. rkpradeep20@gmail.com.

akashvercetti commented 6 years ago

Please forward the working sample app to me at carljohnson.akash@gmail.com

Or post it somewhere on github

akashvercetti commented 6 years ago

@iThink32 I think the best solution would be to make a new .open function where you would let us choose the presenting controller and let us decide if we want to push or present. This is probably the best and most flexible solution for everyone.

iThink32 commented 6 years ago

@akashvercetti suggestion taken will take this up for the next release.Anyway regarding the sample app , as of now we have not uploaded any Swift sample app so ill modify the one @rkpradeep20 has sent and send it to both of you in a while.

iThink32 commented 6 years ago

@rkpradeep20 I just saw your project and this is what is actually happening , you are presenting a navigation controller on Screen A (suppose) and then calling pay on the first controller embedded in your presented navigation controller.

Now since I'm checking whether the rootviewcontroller is a navigation controller which in your case is not i.e Screen A so im presenting razorpay's navigation controller , now iOS is not allowing another another navigation controller to be presenting when one is already being presented and that is the reason for which Razorpay's payment screen is not being presented.

The possible are that

Abishek10 commented 6 years ago

@iThink32 Please mail the working sample app to abishek@mykarmaapp.com

akashvercetti commented 6 years ago

@rkpradeep20 I just saw your project and this is what is actually happening , you are presenting a navigation controller on Screen A (suppose) and then calling pay on the first controller embedded in your presented navigation controller.

Now since I'm checking whether the rootviewcontroller is a navigation controller which in your case is not i.e Screen A so im presenting razorpay's navigation controller , now iOS is not allowing another another navigation controller to be presenting when one is already being presented and that is the reason for which Razorpay's payment screen is not being presented.

The possible are that

  • you have to present it from Screen A or make your rootViewController a navigation controller.
  • you have to use the delegation pattern and dismiss your navController from Screen A for the payment and call the open method.

But what if I have Navigation controller presented over a rootviewController(TabBarController), and a second view controller presented on top of it. Now to present the Razorpay scene, according to your solution, I would have to dismiss a whole lot of controllers before calling .open but that is not consistent with the UX that we want for the user. Please consider this use case and release a new pod with my suggested fix.

iThink32 commented 6 years ago

@akashvercetti its not a good approach to present a viewController over a navigationController ,you must push it on the stack.Anyway the next release will have the open(displayController:) method with which you can specify the viewController on which our Controller has to be displayed.

iThink32 commented 6 years ago

@rkpradeep20 the next release will have the open(displayController:) method with which you can specify the viewController on which our Controller has to be displayed.

akashvercetti commented 6 years ago

@akashvercetti its not a good approach to present a viewController over a navigationController ,you must push it on the stack.Anyway the next release will have the open(displayController:) method with which you can specify the viewController on which our Controller has to be displayed.

I guess I didn't explain it properly, We present it over a view Controller at the top of the navigation controller stack, not the navigation controller itself. But I guess I will have to wait for the next release.

iThink32 commented 6 years ago

@akashvercetti ok

iThink32 commented 6 years ago

@akashvercetti a new version has been released , please update.

iThink32 commented 6 years ago

closing as this issue has been fixed , please reopen if you continue facing any issue

ShahnaHassan commented 5 years ago

can anyone help me with the simplest solution for this issue?

iThink32 commented 5 years ago

@ShahnaHassan this issue has been fixed long back , please refer the readme for more details.

ShahnaHassan commented 5 years ago

Sir, I would like to know how can we get the payment details like paid amount payment mode etc..by passing the paymentId. Kindly reply me as soon as possible.

On Thu, Dec 27, 2018 at 3:13 PM Shashank notifications@github.com wrote:

@ShahnaHassan https://github.com/ShahnaHassan this issue has been fixed long back , please refer the readme for more details.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/razorpay/razorpay-pod/issues/38#issuecomment-450116145, or mute the thread https://github.com/notifications/unsubscribe-auth/AkIyWK-m3Vd1kFO1xPt4zlFJFPlj7veyks5u9JY7gaJpZM4W-QIF .

ShahnaHassan commented 5 years ago

Sir, The thing is that i want to do refund using razorpay...so i want to find wether full refund or partial refund is going to take place. please help me...i searched the documentation but i couldnt find it for IOS. Thank You!

On Thu, Jan 3, 2019 at 10:50 AM Shahna Hassan shahna.c.t666@gmail.com wrote:

Sir, I would like to know how can we get the payment details like paid amount payment mode etc..by passing the paymentId. Kindly reply me as soon as possible.

On Thu, Dec 27, 2018 at 3:13 PM Shashank notifications@github.com wrote:

@ShahnaHassan https://github.com/ShahnaHassan this issue has been fixed long back , please refer the readme for more details.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/razorpay/razorpay-pod/issues/38#issuecomment-450116145, or mute the thread https://github.com/notifications/unsubscribe-auth/AkIyWK-m3Vd1kFO1xPt4zlFJFPlj7veyks5u9JY7gaJpZM4W-QIF .

iThink32 commented 5 years ago

@ShahnaHassan both of the above have to done via the admin dashboard , there is no provision for it via the SDK.

ShahnaHassan commented 5 years ago

Thank You Sir

On Thu, Jan 3, 2019 at 1:07 PM Shashank notifications@github.com wrote:

@ShahnaHassan https://github.com/ShahnaHassan both of the above have to done via the admin dashboard , there is no provision for it via the SDK.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/razorpay/razorpay-pod/issues/38#issuecomment-451072310, or mute the thread https://github.com/notifications/unsubscribe-auth/AkIyWKg7EVHFwtZ6IkfbrhNwtenvUp5_ks5u_bNPgaJpZM4W-QIF .

ShahnaHassan commented 5 years ago

I would also like to know whether will you provide these functionalities in future via SDK?

On Thu, Jan 3, 2019 at 1:45 PM Shahna Hassan shahna.c.t666@gmail.com wrote:

Thank You Sir

On Thu, Jan 3, 2019 at 1:07 PM Shashank notifications@github.com wrote:

@ShahnaHassan https://github.com/ShahnaHassan both of the above have to done via the admin dashboard , there is no provision for it via the SDK.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/razorpay/razorpay-pod/issues/38#issuecomment-451072310, or mute the thread https://github.com/notifications/unsubscribe-auth/AkIyWKg7EVHFwtZ6IkfbrhNwtenvUp5_ks5u_bNPgaJpZM4W-QIF .

iThink32 commented 5 years ago

@ShahnaHassan its currently not in our roadmap as of now , will update the readme if we expose such a feature in future.

ShahnaHassan commented 5 years ago

Thank you!

Rushi271193 commented 5 years ago

Attempt to present <UINavigationController: 0x7f8c6390ae00> on <UIViewController: 0x7f8c6341fe90> which is already presenting <RCTModalHostViewController: 0x7f8c6349b7a0> /Users/travis/build/razorpay/razorpay-ios/RazorpayIOS/CheckoutOtpelf/Classes/RazorpayCheckoutVC.swift deinitialized

getting this issue for react native razorpay. As you have mentioned there ways to solve it in native ios but how do we overcome it in react native as we dont use the viewcontrollers to push any view

DhrubojyotiBis1 commented 4 years ago

I am facing this problem now.

kingglov commented 4 years ago

For me its worked and my scenario is , Screenshot 2019-12-20 at 11 09 00

first i have a login view Controller , after login or skipping that it takes to a tabbar controller . after that i've selected a product and try to present the rozarpay but its showing the error that not in window hierarchy .

Screenshot 2019-12-20 at 11 11 19

Here i found the reason that my root controller is login view controller but i am presenting in tabbar controller . and i've implemented if user pressed skip or logged it should check in the app deligate and set the root controller inside the appDeligate. so now if you close and reopen the app(not run from xcode just close and reopen) in device or simulator the app deligate sets the rootViewController to tabbarcontroller. so , now if you try to call it should work. there is no error and rozarpay was opening.

Screenshot 2019-12-20 at 11 12 23

And the final solution is set the rootview controller inside login view controller i.e. user pressed skip or logged in. then it should work.

Innovatewithapple commented 4 years ago

Still in 2020 getting the same issue with latest version. And cannot find any solution yet. please help me... I searched the documentation but I couldn't find it

Thanks in advanced