在推送其ViewController之前如何预加载WKWebView?

时间:2019-01-02 16:32:58

标签: ios swift loading wkwebview preload

我问这个问题是因为经过一些研究,我在网上找不到令人满意的答案。

我的需求很简单,我有一个UITableViewController,当我单击一个单元格时,我需要显示一个加载器(在加载WKWebViewContent的同时),然后推送下一个UIViewController,并且已经在其中加载了WKWebView。

我尝试过:

class TableViewController: UITableViewController, WKNavigationDelegate {

   var webviewToLoad:WKWebView!

    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

        let htmlString = "some html content"


        webviewToLoad = WKWebView(frame: .zero, configuration: WKWebViewConfiguration())
        webviewToLoad.navigationDelegate = self
        webviewToLoad.loadHTMLString(htmlString, baseURL: Bundle.main.resourceURL)
    }

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

        if segue.identifier == "postview"{
            let destinationController = segue.destination as! ViewController
            destinationController.webView= webviewToLoad
        }
    }

    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        print("Loaded!")
        self.performSegue(withIdentifier: "postview", sender: self)
    }

}

class ViewController: UIViewController, WKUIDelegate {

    var webView: WKWebView!

    override func loadView() {

        let webConfiguration = WKWebViewConfiguration()
        webView = WKWebView(frame: .zero, configuration: webConfiguration)
        webView.uiDelegate = self
        self.view = webView
    }

    override func viewDidLoad() {
        super.viewDidLoad()
    }
}

didFinish被调用,但最终的WKWebView为空。

也许这不是正确的方法,有什么想法吗?

2 个答案:

答案 0 :(得分:1)

  

didFinish被调用,但最终的WKWebView为空

因为您从未做过任何使它 not 为空白的操作。您的代码说:

var webviewToLoad:WKWebView!
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    webviewToLoad = WKWebView(frame: .zero, configuration: WKWebViewConfiguration())
    webviewToLoad.navigationDelegate = self
    webviewToLoad.loadHTMLString(htmlString, baseURL: Bundle.main.resourceURL)
}

因此,您所做的一切都是关于webviewToLoad。但是webviewToLoad与在出现以下问题之后在ViewController中出现的webView不是相同的class ViewController: UIViewController, WKUIDelegate { var webView: WKWebView! }

webView

是您要为其提供内容的Web视图。您根本没有这样做;您的代码都没有碰到if segue.identifier == "postview"{ let destinationController = segue.destination as! ViewController destinationController.webView = webviewToLoad } 来提供内容。

我认为您的困惑的核心在这里:

loadView

您不能仅将一个Web视图替换为另一个Web视图,并期望一切都能神奇地工作; if segue.identifier == "postview"{ let destinationController = segue.destination as! ViewController // make `loadView` run destinationController.loadViewIfNeeded() let webView = destinationController.webView // now load _this_ `webView` with content! let htmlString = "some html content" webView.loadHTMLString(htmlString, baseURL: Bundle.main.resourceURL) } 仍将使原始的空白Web视图成为您的视图并出现在界面中。

相反,您想要的是这种体系结构:

Repository

答案 1 :(得分:1)

由于@matt的回答不完整,因此我的解决方案是在推送下一个视图控制器之前等待webview加载:

class TableViewController: UITableViewController, WKNavigationDelegate, WKUIDelegate {

    var webviewToLoad:WKWebView!
    var destinationController:ViewController!
    var alert:UIAlertController!

    override func viewDidLoad() {
        super.viewDidLoad()       
    }

    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

        alert = UIAlertController(title: "Alert", message: "Loading", preferredStyle: .alert)

        destinationController = UIStoryboard.init(name: "Main", bundle: Bundle.main).instantiateViewController(withIdentifier: "ViewController") as? ViewController

        destinationController!.loadViewIfNeeded()
        let webView:WKWebView = destinationController!.webView
        webView.navigationDelegate = self
        webView.uiDelegate = self

        self.present(alert, animated: true, completion: nil)

        let htmlString = "my html code"
        webView.loadHTMLString(htmlString, baseURL: Bundle.main.resourceURL)
    }


    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {

        alert.dismiss(animated: false, completion: nil)
        self.navigationController?.pushViewController(destinationController!, animated: true)
    }

}

还有带有Webview的UIViewController:

class ViewController: UIViewController, WKUIDelegate, WKNavigationDelegate {

    var webView: WKWebView!
    @IBOutlet var viewForWebview: UIView!
    @IBOutlet var heightWebviewConstraint: NSLayoutConstraint!

    override func viewDidLoad() {
        super.viewDidLoad()

    }

     override func loadView() {

        super.loadView()

        webView = WKWebView()

        if (webView != nil) {
            webView!.frame = viewForWebview.frame

            webView.translatesAutoresizingMaskIntoConstraints = false

            viewForWebview.addSubview(webView!)

            NSLayoutConstraint.activate([
               webView.topAnchor.constraint(equalTo: viewForWebview.topAnchor),
                webView.bottomAnchor.constraint(equalTo: viewForWebview.bottomAnchor),
                webView.leadingAnchor.constraint(equalTo: viewForWebview.leadingAnchor),
                webView.trailingAnchor.constraint(equalTo: viewForWebview.trailingAnchor)
                ])
        }

    }


    override func viewDidLayoutSubviews() {

        super.viewDidLayoutSubviews()

        heightWebviewConstraint.constant = self.webView.scrollView.contentSize.height
        self.view.setNeedsLayout()
        self.view.setNeedsUpdateConstraints()


    }    
}

此代码在加载Webview时显示UIAlertController,然后关闭警报控制器,并在已加载Webview的情况下推送下一个控制器。