Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to find current UIViewController in Xamarin

I am using the Facebook Auth SDK, with a Xamarin Forms C# example. However, the Facebook SDK has depreciated the method and replaced it with one which adds a fromViewController variable into the constructors. I am not particularly comfortable with the concept of ViewControllers in Xamarin, or indeed with this code as it is from a sample, so is there a way to gauge the current ViewController?

I have seen a few .net examples e.g. NSArray *viewContrlls=[[self navigationController] viewControllers];[viewContrlls lastObject]; However, this approach doesn't seem to work with Xamarin, as self doesn't contain definitions for navigationControllers.

Alternatively, is there any way of easily working out which variable my current ViewController is sotored in, using the sample code?

like image 726
George Edwards Avatar asked Jan 03 '16 23:01

George Edwards


2 Answers

Update This method has become a bit more complex in order to support newer iOS versions in race conditions. This is the new version of the utility with some improvements:

public static UIViewController GetTopViewController()
{
    var window = UIApplication.SharedApplication.GetKeyWindow();
    var vc = window?.RootViewController;
    while (vc is { PresentedViewController: { } })
        vc = vc.PresentedViewController;

    if (vc is UINavigationController { ViewControllers: { } } navController) 
        vc = navController.ViewControllers.Last();

    return vc;
}

public static UIWindow GetKeyWindow(this UIApplication application)
{
    if (!UIDevice.CurrentDevice.CheckSystemVersion(13, 0)) 
        return application.KeyWindow; // deprecated in iOS 13
    
    var window = application
        .ConnectedScenes
        .ToArray()
        .OfType<UIWindowScene>()
        .SelectMany(scene => scene.Windows)
        .FirstOrDefault(window => window.IsKeyWindow);

    return window;
}

Old answer

The accepted answer won´t give you the current view controller if it´s in the stack of a parent UINavigationController, so I came up with the following:

public static UIViewController GetTopViewController()
{
    var window = UIApplication.SharedApplication.KeyWindow;
    var vc = window.RootViewController;
    while (vc.PresentedViewController != null)
        vc = vc.PresentedViewController;

    if (vc is UINavigationController navController)
        vc = navController.ViewControllers.Last();

    return vc;
}
like image 112
xleon Avatar answered Nov 15 '22 21:11

xleon


The best way to do this is to pass in a reference to the ViewController that is calling the Auth method.

However, you can also try this approach (courtesy of AdamKemp on the Xamarin Forums)

var window= UIApplication.SharedApplication.KeyWindow;
var vc = window.RootViewController;
while (vc.PresentedViewController != null)
{
    vc = vc.PresentedViewController;
}
like image 25
Jason Avatar answered Nov 15 '22 20:11

Jason