Reputation: 17670
Situation
An iOS app built in Xamarin with 4 screens. When you start the app it attempts to retrieve information to populate the first screen. If user token expired an exception is thrown. The AppDelegate listens for these messages and when received will show the login screen:
_window.RootViewController.PresentViewController(_loginViewController, true, null);
(_window
is the first screen. _loginViewController
is the screen the user enters their username and password.)
This works OK when on the first screen. But I need a way to show _loginViewController
from ANY screen.
Problem/Questions
Note: My project is in Xamarin and supports iOS 8+ but I'm sure if I got a Swift solution I could work with that as well.
Upvotes: 1
Views: 539
Reputation: 12190
You can find the top-most view controller through the following code defined as a static property on your AppDelegate
:
[Register("AppDelegate")]
public partial class AppDelegate : UIApplicationDelegate
{
public static UIViewController TopViewController
{
get
{
return TopViewControllerWithRootViewController(UIApplication.SharedApplication.KeyWindow.RootViewController);
}
}
public static UIViewController TopViewControllerWithRootViewController(UIViewController rootViewController)
{
if (rootViewController is UITabBarController)
{
var tabBarController = rootViewController as UITabBarController;
return TopViewControllerWithRootViewController(tabBarController.SelectedViewController);
}
if (rootViewController is UINavigationController)
{
var navBarController = rootViewController as UINavigationController;
return TopViewControllerWithRootViewController(navBarController.VisibleViewController);
}
var presentedViewController = rootViewController.PresentedViewController;
if (presentedViewController != null)
{
return TopViewControllerWithRootViewController(presentedViewController);
}
return rootViewController;
This is a C# port of this answer.
To present a view controller from anywhere in you app, use the above code like so:
MFMailComposeViewController mailController = new MFMailComposeViewController();
// ...
AppDelegate.TopViewController.PresentViewController(mailController, true, null);
Upvotes: 1
Reputation: 9703
You could create a method in the AppDelegate like so:
public void ShowLoginView()
{
_window.RootViewController.PresentViewController(_loginViewController,true,null);
}
Then Call it from any ViewController like so:
var appDelegate = (AppDelegate)UIApplication.SharedApplication.Delegate;
appDelegate.ShowLoginView ();
And Dismiss it in the LoginViewController with this:
DismissModalViewController (true);
This will allow you to keep your navigation stack if you are using one.
Upvotes: 0
Reputation: 30883
You can use the following code to show login screen from AppDelegate regardless of the current window:
var loginViewController = UIStoryboard.FromName("MainStoryboard", NSBundle.MainBundle).InstantiateViewController("LoginPageViewController") as LoginPageViewController;
Window.RootViewController = loginViewController;
Upvotes: 1