6

我有一个 UIView,它有一个 WKWebView 作为子视图。Web 视图显示正常,但显示 HTML 文档需要很长时间(超过一秒)。该文档是本地文件(项目中的 HTML 文件),因此没有 Internet 延迟,是一个相对简单的 HTML 文档。HTML 文档上确实有八个小图像,但是另一个没有任何图像的 HTML 文档也存在类似的问题。

以下是将 HTML 文档加载到 Web 视图中的代码:

override func viewDidLoad() {
    super.viewDidLoad()
    let localHtmlFile = Bundle.main.url(forResource: "place", withExtension: "html");
    let request = URLRequest(url: localHtmlFile!);
    webView.load(request);
}

我正在使用 Xcode 9.3、Swift 4.1 和 iOS 11.2。

每次我进入该屏幕时都会发生延迟。如果第一次无法防止延迟,是否可以保留 web 视图以使延迟只发生一次?

4

2 回答 2

3

显然,延迟是由创建 的新实例所花费的时间引起的WKWebView,而不是由加载 HTML 文档所花费的时间引起的。为了避免这种延迟,我想出了一种重用 Web 视图的方法。

首先,我从情节提要场景中删除了 Web 视图,这样每次加载视图时都不会创建新的 Web 视图。我制作了一个通用视图,名称container与我想要的 Web 视图大小相同。

然后我创建了一个静态变量来保存指向 web 视图的指针:
static var webView: WKWebView? = nil
在我的例子中,这个静态变量在一个名为GameController.

接下来我更改了代码以检查静态webView变量是否为 nil。如果webView为 nil,代码将创建一个新的 Web 视图并将静态变量设置为指向该 Web 视图。然后代码以编程方式将 Web 视图添加为故事板场景中容器视图的子视图。

为了设置故事板并编写此代码,我使用了以下网站上的说明:
http ://www.onebigfunction.com/ios/2016/12/14/iOS-javascript-communication/

使用 Web 视图的场景的视图控制器中的基本代码(WebViewController在我的代码中)如下所示:

override func loadView() {
    super.loadView()
    if GameController.webView == nil {
        var webFrame = self.container!.frame
        webFrame.origin.x = 0
        webFrame.origin.y = 0
        let config = WKWebViewConfiguration()
        webView = WKWebView(frame: webFrame,
                            configuration: config)
        GameController.webView = webView
    } else {
        webView = GameController.webView
    }
    self.container!.addSubview(webView)
}

就我而言,我想将信息从 web 视图中的 JavaScript 代码发送到我的应用程序中的 Swift 代码,因此我不得不更多地使用配置。我还希望 web 视图是透明的,所以我添加了一个声明来做到这一点。

override func loadView() {
    super.loadView()
    if GameController.webView == nil {
        var webFrame = self.container!.frame
        webFrame.origin.x = 0
        webFrame.origin.y = 0
        let config = WKWebViewConfiguration()
        config.userContentController.add(self, name: "scriptHandler")
        webView = WKWebView(frame: webFrame,
                            configuration: config)
        webView.isOpaque = false
        GameController.webView = webView
    } else {
        webView = GameController.webView
        webView.configuration.userContentController.removeScriptMessageHandler(
            forName: "scriptHandler")
        webView.configuration.userContentController.add(self,
             name: "scriptHandler")
    }
    self.container!.addSubview(webView)
}

最初我只在第一次制作 web 视图时设置脚本处理程序,但这不起作用。显然,每次加载场景时都会创建一个新的视图控制器对象,因此旧的脚本处理程序不起作用。此代码删除指向旧视图控制器的脚本处理程序并添加指向新视图控制器的脚本处理程序。

于 2018-06-14T20:38:43.703 回答
0

只需保留对 ViewController 的引用,可能在父控制器、应用程序委托甚至单例/全局中。在后续加载时它应该会更快一些。

于 2018-05-26T04:33:22.340 回答