如何在 Xamarin 中查找当前的 UIViewController

How to find current UIViewController in Xamarin

我正在使用Facebook Auth SDK, with a Xamarin Forms C# example。然而,Facebook SDK 已经弃用了该方法,并将其替换为将 fromViewController 变量添加到构造函数中的方法。我对 Xamarin 中的 ViewControllers 的概念不是特别满意,或者实际上这个代码来自示例,所以有没有办法衡量当前的 ViewController?

我看过一些 .net 示例,例如NSArray *viewContrlls=[[self navigationController] viewControllers];[viewContrlls lastObject]; 但是,这种方法似乎不适用于 Xamarin,因为 self 不包含导航控制器的定义。

或者,是否有任何方法可以使用示例代码轻松计算出当前 ViewController 存储在哪个变量中?

执行此操作的最佳方法是传入对调用 Auth 方法的 ViewController 的引用。

不过,您也可以尝试这种方法(由 Xamarin Forums 上的 AdamKemp 提供)

var window= UIApplication.SharedApplication.KeyWindow;
var vc = window.RootViewController;
while (vc.PresentedViewController != null)
{
    vc = vc.PresentedViewController;
}

更新 为了在竞争条件下支持更新的 iOS 版本,此方法变得有点复杂。这是该实用程序的新版本,有一些改进:

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;
}

旧答案

如果当前视图控制器位于父对象的堆栈中,则接受的答案不会为您提供当前视图控制器UINavigationController,因此我得出以下结论:

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;
}