You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Xamarin iOS:从ContentPage跳转UIViewController后返回按钮失效问题

解决从ContentPage打开UIViewController后无法返回的问题

你的问题出在直接创建了一个全新的UIWindow并替换了应用的根控制器,这导致原来的ContentPage所在的视图控制器层级被完全隔离,所以PopViewController和DismissViewController都无法找到要返回的页面——新窗口的导航栈里只有ScanningPage,而且原来的页面根本不在这个新窗口的层级体系中。

下面是两种可行的解决方案,优先推荐第一种:

方案一:用PresentViewController打开(符合iOS视图层级规范)

这是最标准的方式,通过获取当前应用的顶级视图控制器,以模态方式打开你的ScanningPage,这样就能正常用Dismiss返回。

步骤1:在共享项目定义接口

public interface INativePageService
{
    void OpenScanningPage();
}

步骤2:在iOS项目实现接口

[assembly: Dependency(typeof(NativePageService))]
namespace YourAppNamespace.iOS
{
    public class NativePageService : INativePageService
    {
        public void OpenScanningPage()
        {
            // 获取当前显示的顶级视图控制器
            var currentVC = UIApplication.SharedApplication.KeyWindow.RootViewController;
            while (currentVC.PresentedViewController != null)
            {
                currentVC = currentVC.PresentedViewController;
            }

            // 创建你的扫描页面和导航控制器
            var scanningPage = new ScanningPage();
            var navController = new UINavigationController(scanningPage);
            
            // 以模态方式打开
            currentVC.PresentViewController(navController, true, null);
        }
    }
}

步骤3:在ScanningPage添加返回按钮

public override void ViewDidLoad()
{
    base.ViewDidLoad();

    // 添加导航栏返回按钮
    var backBtn = new UIBarButtonItem("返回", UIBarButtonItemStyle.Plain, (s, e) =>
    {
        // 现在Dismiss就能回到原来的ContentPage了
        this.DismissViewController(true, null);
    });
    this.NavigationItem.LeftBarButtonItem = backBtn;
}

方案二:保留原窗口(特殊场景使用)

如果因为某些需求必须用新窗口,那需要保存原来的KeyWindow,关闭新窗口时恢复它:

打开新窗口时保存原窗口

// 保存原来的主窗口
var originalWindow = UIApplication.SharedApplication.KeyWindow;

// 创建新窗口并设置根控制器
var newWindow = new UIWindow(UIScreen.MainScreen.Bounds);
var scanningPage = new ScanningPage();
var navController = new UINavigationController(scanningPage);
newWindow.RootViewController = navController;
newWindow.MakeKeyAndVisible();

// 将原窗口传递给ScanningPage(可以用静态属性)
ScanningPage.OriginalMainWindow = originalWindow;

在ScanningPage中恢复原窗口

public static UIWindow OriginalMainWindow { get; set; }

public override void ViewDidLoad()
{
    base.ViewDidLoad();

    var backBtn = new UIBarButtonItem("返回", UIBarButtonItemStyle.Plain, (s, e) =>
    {
        // 恢复原来的主窗口
        OriginalMainWindow.MakeKeyAndVisible();
        // 释放新窗口资源
        this.View.Window.ResignKey();
        this.View.Window.Dispose();
    });
    this.NavigationItem.LeftBarButtonItem = backBtn;
}

为什么原来的方法不行?

你原来的代码直接创建了新的UIWindow并调用MakeKeyAndVisible(),这会把应用的主窗口替换成新窗口,原来的ContentPage所在的视图控制器层级被“覆盖”了——新窗口的导航栈里只有ScanningPage,所以PopViewController没有上一个页面可返回;而DismissViewController要求当前控制器是被模态Present出来的,你直接把它设为根控制器,自然无法触发Dismiss逻辑。

内容的提问来源于stack exchange,提问作者Mannu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 12:17:47