简体   繁体   English

iOS应用中的WKWebView加载时间很长

[英]WKWebView in iOS app takes a long time to load

I have a UIView that has a WKWebView as a subview. 我有一个将WKWebView作为子视图的UIView。 The web view shows up all right, but it takes a long time (more than a second) to display the HTML document. 可以正常显示Web视图,但是显示HTML文档需要很长时间(超过一秒钟)。 The document is a local file (an HTML file in the project) so there is no Internet latency, and it's a relatively simple HTML document. 该文档是本地文件(项目中的HTML文件),因此没有Internet延迟,并且它是相对简单的HTML文档。 The HTML document does have eight small images on it, but there is a similar problem with another HTML document that doesn't have any images. HTML文档上确实有八个小图像,但是另一个没有任何图像的HTML文档也存在类似的问题。

Here's the code that loads the HTML document into the web view: 以下是将HTML文档加载到网络视图中的代码:

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

I am using Xcode 9.3, Swift 4.1, and iOS 11.2. 我正在使用Xcode 9.3,Swift 4.1和iOS 11.2。

The delay happens every time I go to that screen. 每次我进入该屏幕时都会发生延迟。 If it isn't possible to prevent the delay the first time, is it possible to keep the web view around so that the delay only happens once? 如果无法第一次阻止延迟,是否可以保持Web视图周围,以便延迟仅发生一次?

Apparently the delay is caused by the time it takes to make a new instance of WKWebView , not the time it takes to load an HTML document. 显然,延迟是由创建WKWebView的新实例所WKWebView的时间WKWebView ,而不是由加载HTML文档所花费的时间引起的。 To avoid that delay I figured out a way to reuse a web view. 为了避免这种延迟,我想出了一种重复使用Web视图的方法。

First I removed the web view from the storyboard scene so that a new web vew wouldn't be created every time the view was loaded. 首先,我从情节提要板场景中删除了Web视图,以使每次加载视图时都不会创建新的Web Vew。 I made a generic view named container that is the same size that I wanted the web view to be. 我创建了一个名为container的通用视图,该视图的大小与Web视图的大小相同。

Then I made a static variable to keep a pointer to the web view: 然后,我做了一个静态变量来保持指向Web视图的指针:
static var webView: WKWebView? = nil
In my case this static variable is in a class called GameController . 在我的情况下,此静态变量在名为GameController的类中。

Next I changed the code to check to see if the static webView variable is nil. 接下来,我更改了代码以检查静态webView变量是否为nil。 If webView is nil, the code creates a new web view and sets the static variable to point to that web view. 如果webView为nil,则代码将创建一个新的Web视图,并将静态变量设置为指向该Web视图。 Then the code programmatically adds the web view as a subview of a container view in the storyboard scene. 然后,代码以编程方式将Web视图添加为情节提要场景中容器视图的子视图。

To set up the storyboard and write this code I used the explanation on the following web site: 为了设置情节提要并编写此代码,我在以下网站上使用了说明:
http://www.onebigfunction.com/ios/2016/12/14/iOS-javascript-communication/ http://www.onebigfunction.com/ios/2016/12/14/iOS-javascript-communication/

The basic code in the view controller for the scene that uses the web view ( WebViewController in my code) looks like this: 使用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)
}

In my case, I wanted to send information from JavaScript code in the web view to Swift code in my app, so I had to work more with configurations. 就我而言,我想将信息从Web视图中的JavaScript代码发送到我的应用程序中的Swift代码,因此我不得不在配置方面做更多工作。 I also wanted the web view to be transparent, so I added a statement to do that. 我还希望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)
}

Originally I only set the script handler when I first made the web view, but that didn't work. 最初,我仅在首次创建Web视图时设置脚本处理程序,但这没有用。 Apparently a new view controller object was made each time the scene was loaded, so the old script handler didn't work. 显然,每次加载场景时都会创建一个新的视图控制器对象,因此旧的脚本处理程序不起作用。 This code deletes the script handler that pointed to the old view controller and adds a script handler that points to the new view controller. 此代码将删除指向旧视图控制器的脚本处理程序,并添加一个指向新视图控制器的脚本处理程序。

Just keep a reference to the ViewController, perhaps in a parent controller, app delegate, or even a singleton/global. 只需保留对ViewController的引用,也许是在父控制器,应用程序委托乃至单例/全局中。 It should be somewhat faster on subsequent loads. 在后续加载中应该更快一些。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM