Xamarin.iOS 中的 Web 视图

在 iOS 的整个生命周期内,Apple 发布了许多方法让应用开发人员能够将 Web 视图功能整合到其应用中。 大多数用户在其 iOS 设备上利用内置的 Safari Web 浏览器,因此期望其他应用中的 Web 视图功能与此体验一致。 他们期望能使用相同的手势、有媲美的性能和相同的功能。

iOS 11 引入了对 WKWebViewSFSafariViewController 的新更改。 有关这些内容的详细信息,请参阅 iOS 11 指南的 Web 更改

WKWebView

在 iOS 8 中引入了 WKWebView,它让应用开发人员能够实现类似于移动版 Safari 的 Web 浏览界面。 这部分是由于 WKWebView 使用了 Nitro Javascript 引擎,移动版 Safari 也使用此引擎。 只要可能,总是应在 UIWebView 上使用 WKWebView,因为它可提高性能、内置有用户友好的手势,并且易于在网页和应用之间进行交互。

WKWebView 可采用与 UIWebView 几乎相同的方式添加到应用中,然而身为开发人员,你能够更好地控制 UI/UX 和功能。 创建和显示 Web 视图对象将显示请求的页面,但你可以控制视图的显示方式、用户导航的方式以及用户退出视图的方式。

下面的代码可用于在 Xamarin.iOS 应用中启动 WKWebView

WKWebView webView = new WKWebView(View.Frame, new WKWebViewConfiguration());
View.AddSubview(webView);

var url = new NSUrl("https://learn.microsoft.com");
var request = new NSUrlRequest(url);
webView.LoadRequest(request);

请务必注意,WKWebViewWebKit 命名空间中,因此必须将此 using 指令添加到类的顶部。

WKWebView 也可在 Xamarin.Mac 应用中使用;如果要创建跨平台 Mac/iOS 应用,则应使用它。

处理 JavaScript 警报手册还介绍了如何将 WKWebView 与 Javascript 配合使用。

SFSafariViewController

SFSafariViewController 是从应用中提供 Web 内容的最新方法,在 iOS 9 及更高版本中可用。 与 UIWebViewWKWebView 不同,SFSafariViewController 是视图控制器,因此不能与其他视图一起使用。 应将 SFSafariViewController 显示为新的视图控制器,就像呈现任何视图控制器一样。

SFSafariViewController 本质上是一个可嵌入到应用中的“迷你 Safari”。 与 WKWebView 一样,它使用相同的 Nitro Javascript 引擎,但还提供了一系列其他 Safari 功能,例如自动填充、阅读器,以及与移动版 Safari 共享 Cookie 和数据的功能。 你的应用无法访问用户与 SFSafariViewController 之间的交互。 你的应用将无法访问任何默认 Safari 功能。

默认情况下,它还实现一个“完成”按钮,让用户能够轻松返回应用,还提供前进和后退导航按钮,让用户能够在一系列网页中浏览。 此外,它还为用户提供一个地址栏,让他们确信自己在预期的网页上。 地址栏不允许用户更改 URL。

无法更改这些实现,因此如果你的应用应用在不进行任何自定义的情况下呈现网页,SFSafariViewController 非常适合用作默认浏览器。

下面的代码可用于在 Xamarin.iOS 应用中启动 SFSafariViewController

var sfViewController = new SFSafariViewController(url);

PresentViewController(sfViewController, true, null);

这会生成以下 Web 视图:

An example web view with SFSafariViewController

Safari

也可使用以下代码从应用中打开移动版 Safari 应用:

var url = new NSUrl("https://learn.microsoft.com");

UIApplication.SharedApplication.OpenUrl(url);

这会生成以下 Web 视图:

A web page presented in Safari

通常,应始终避免将用户从你的应用导航到 Safari。 大多数用户都不希望在应用程序外部导航,因此如果你从你的应用导航离开,用户可能永远不会返回,这基本上会破坏用户粘性。

iOS 9 改进使得用户能够通过 Safari 页面左上角提供的后退按钮轻松返回到你的应用。

应用传输安全性

Apple 在 iOS 9 中引入了应用传输安全 (ATS),以确保所有 Internet 通信都符合安全连接最佳做法。

有关 ATS 的详细信息,包括如何在应用中实现它,请参阅应用传输安全指南。

UIWebView 弃用

UIWebView 是 Apple 在应用中提供 Web 内容的旧方法。 它在 iOS 2.0 中发布,自 8.0 起已弃用。

重要

UIWebView 已弃用。 从 2020 年 4 月起,使用此控件的新应用将不被 App Store 接受,而在 2020 年 12 月之前,使用此控件的应用更新将不被接受。

Apple 的 UIWebView 文档建议应用转而使用 WKWebView

使用 Xamarin.Forms 时,若要查看关于 UIWebView 的弃用警告 (ITMS-90809) 的相关资源,请参阅 Xamarin.Forms WebView 文档。

在过去 6 个月(左右)提交 iOS 应用程序的开发人员可能会收到来自 App Store 的警告,显示 UIWebView 即将被弃用。

API 被弃用的情况很常见。 Xamarin.iOS 使用自定义属性将这些 API 反馈给开发人员(并建议在可用时替换)。 这次的不同之处是(这种情况更不常见),在提交时,Apple 的 App Store 将强制弃用。

遗憾的是,从 Xamarin.iOS.dll 中删除 UIWebView 是一项二进制中断性变更。 此更改将中断现有的第三方库,包括一些可能不受支持甚至不再可重新编译的库(例如封闭源)。 这只会给开发人员带来额外的问题。 因此,我们尚未删除该类型。

Xamarin.iOS 13.16 开始,有新的检测和工具来帮助你从 UIWebView 进行迁移。

检测

如果你近期向 Apple App Store 提交了 iOS 应用程序,你可能想知道这种情况。

若要了解,可以将 --warn-on-type-ref=UIKit.UIWebView 添加到项目的附加 mtouch 参数中。如果引用应用程序(及其所有依赖项)中已弃用的 UIWebView,这将发出警告。 使用不同的警告来报告执行托管链接器之前和之后的类型。

与其他警告一样,可以使用 -warnaserror: 将这些警告转换为错误。 如果想要确保验证后未向 UIWebView 添加新的依赖项,这非常有用。 例如:

  • 如果在链接前的程序集中找到任何引用,-warnaserror:1502 将报告错误。
  • 如果在链接后的程序集中找到任何引用,-warnaserror:1503 将报告错误。

如果链接前/后结果没有用,你还可以将警告静音。 例如:

  • 如果在链接前的程序集中找到任何引用,-nowarn:1502 不会报告警告。
  • 如果在链接后的程序集中找到任何引用,-nowarn:1503 不会报告警告。

删除

每个应用程序都是唯一的。 从应用程序中删除 UIWebView 可能需要不同的步骤,具体取决于它的使用方式和位置。 最常见的场景是:

  • 应用程序内没有使用 UIWebView。 一切都很好。 提交到 AppStore 时,应该不会有警告。 你不需要执行其他任何操作。
  • 应用程序直接使用 UIWebView。 首先移除对 UIWebView 的使用,例如,将其替换为更新的 WKWebView (iOS 8) 或 SFSafariViewController (iOS 9) 类型。 完成此操作后,托管链接器应该就不会看到对 UIWebView 的任何引用,并且最终应用二进制文件也没有它的跟踪。
  • 间接使用。 UIWebView 可以存在于应用程序托管或本机使用的某些第三方库中。 首先,将外部依赖项更新到其最新版本,因为这种情况可能已在更新的版本中得到解决。 如果没有,请联系库的维护人员,并询问其更新计划。

或者,可尝试以下方法:

  1. 如果使用的是 Xamarin.Forms,请阅读这篇博客文章
  2. 启用托管链接器(针对整个项目或至少针对使用 UIWebView 的依赖项),以便可在未引用它时删除它。 这将解决问题,但可能需要执行额外的工作才能使代码链接器安全。
  3. 如果无法更改托管链接器设置,请查看下面的特殊情况。

应用程序无法使用链接器(或更改其设置)

如果你由于某种原因没有使用托管链接器(例如“请勿链接”),则 UIWebView 符号将保留在你提交到 Apple 的二进制应用中,并且它可能会被拒绝。

强制解决方案是将 --optimize=force-rejected-types-removal 添加到项目的附加 mtouch 参数。 这会从应用程序中删除 UIWebView 的跟踪。 但是,引用该类型的任何代码都将无法正常工作(预期出现异常或崩溃)。 仅当确保代码在运行时不可访问时(即使可通过静态分析访问),才应使用此方法。

支持 iOS 7.x(或更低版本)

自 v2.0 以来,UIWebView 一直是 iOS 的一部分。 最常见的替代项是 WKWebView (iOS 8) 和 SFSafariViewController (iOS 9)。 如果应用程序仍支持较旧的 iOS 版本,应考虑以下选项:

  • 将 iOS 8 设为最低目标版本(生成时决策)。
  • 仅当应用在 iOS 8+ 上运行时(运行时决策)才使用 WKWebView

应用程序未提交到 Apple

如果应用程序未提交到 Apple,那么你应计划不使用已弃用的 API,因为它可能会在未来的 iOS 版本中被删除。 但是,可以按照自己的时间表进行这种过渡。