11

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?

George Edwards
  • 8,979
  • 20
  • 78
  • 161

2 Answers2

26

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;
}
xleon
  • 6,201
  • 3
  • 36
  • 52
13

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;
}
Jason
  • 86,222
  • 15
  • 131
  • 146
  • Thanks - I'll try this now! Here is the bit that has confused me slighty. In the sample, you see the `LoginPage()` which just has a button, but the Facebook button is an empty class, which in the ios project has some definitions in `FacebookButtonRenderer.cs`, Which ViewController is active during my PopUp of the facebook login screen. – George Edwards Jan 04 '16 at 10:10