在显示之前加载 ViewController 的 WebView

Load ViewController's WebView before showing

我有一个 ViewController 包含 WebView 的应用程序。因为 WebView 显示的网站非常大,所以我想在应用程序启动时加载 ViewController,所以一旦用户使用 WebView 打开 ViewController,它就会显示已经加载的页。

我试过重写 viewDidLoad()、loadView()、方便的 init() 等,但我放在那里的任何东西似乎都没有在实际显示 ViewController.

之前执行
 let storyboard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
 webViewVC = storyboard.instantiateViewController(withIdentifier: "WebViewController")

 if let c = webViewVC.childViewControllers[0] as? WebViewController {

     c.dDelegate = self

     webViewVC.modalPresentationStyle = .popover
     let popover = webViewVC.popoverPresentationController!
     popover.delegate = self
     popover.permittedArrowDirections = .up
     webViewVC.loadView()
     present(webViewVC, animated: true, completion: nil) //if I don't add this line, the ViewController doesn't seem to get created before showing
 }

那么我可以在 present() 之前调用什么来执行 ViewController 的一些代码?我需要加载如下内容:

let wwConfiguration = WKWebViewConfiguration()

webView = WKWebView(frame: CGRect(x: 0, y: 0, width: self.view.layer.frame.width, height: self.view.layer.frame.height), configuration: wwConfiguration)
webView.navigationDelegate = self
webView.uiDelegate = self
let url = URL(string: . . .

尝试使用 webViewVC.loadViewIfNeeded() 而不是 webViewVC.loadView()

你的问题并不完全清楚,但我假设你从另一个视图控制器展示你的网络视图控制器,比方说,按下按钮。像这样的……

你需要做的是异步处理这个。

  • 实例化您的网络视图控制器
  • 开始加载其网络视图
  • 等待完成
  • 呈现网络视图控制器

例子…

网络ViewController

class WebViewController: UIViewController {

    @IBOutlet private weak var webView: WKWebView!

    var didLoadWebView: (() -> Void)!

    func loadWebView(completion: @escaping () -> Void) {
        loadViewIfNeeded()
        didLoadWebView = completion // Save this closure to be called when loaded
        webView.navigationDelegate = self
        webView.load(URLRequest(url: URL(string: "http://apple.com")!))
    }
}

extension WebViewController: WKNavigationDelegate {
    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        didLoadWebView() // Call back to the presenting view controller
    }
}

呈现ViewController

class ViewController: UIViewController {

    @IBAction func showWebView(_ sender: UIButton) {

        let wvc = storyboard!.instantiateViewController(withIdentifier: "WebViewController") as! WebViewController
        wvc.modalPresentationStyle = .popover
        wvc.popoverPresentationController?.sourceView = sender
        wvc.popoverPresentationController?.sourceRect = sender.bounds
        wvc.loadWebView {
            self.present(wvc, animated: true, completion: nil)
        }
    }
}

好的,让我们尝试了解 OP 的要求。他有一个 viewController 加载网页,根据他的说法,加载时间太长,他不想让用户等待那么久。另外根据他指定启动时间的问题,我认为视图控制器是他将在应用程序启动后显示的第一个视图控制器。

情况 1:webViewVC 是启动后的第一个 VC

这里,我们最大可以获取的"prefetching"时间就是调用方法application:didFinishLaunchingWithOptions:时获取的时间。假设这里没有太多处理器繁重的进程在执行,就没有时间进行预取。因此,唯一的选择是显示一个屏幕,该屏幕在 UI 中应该与 launchScreen 相似,以便用户可能认为它是仍在加载的应用程序。 (就我个人而言,我会做的是将启动屏幕制作成一个只显示应用程序主题颜色的屏幕,并使用应用程序图标左右将我的第一个屏幕设置为启动屏幕;提供更好的专业方法和足够的时间让我让事情顺利进行)

情况2:webViewVC不是第一个VC

在这里,应用程序将在移动到 webViewVC 之前向用户显示另一个 VC,以便我们有一些时间来预取数据。在这种情况下,我将在前一个 VC 的 viewDidLoad 时开始获取数据。 webViewVC 显然会在某些操作后被调用,并且您有时间完成该操作(可能由用户完成)。

正在使用虚拟启动屏幕加载 VC

    let webViewVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "WebViewController") as! WebViewController
    let wwConfiguration = WKWebViewConfiguration()
    let webView = WKWebView(frame: CGRect(x: 0, y: 0, width: view.bounds.width, height: view.bounds.height), configuration: wwConfiguration)
    webView.navigationDelegate = webViewVC
    webView.uiDelegate = webViewVC
    let url = URL(string:"https://www.codemag.com/article/1405051/Understanding-and-Using-iBeacons")
    webView.load(URLRequest(url: url!))
    webViewVC.webView = webView
    DispatchQueue.main.asyncAfter(deadline: .now() + 10.0) {
        webViewVC.modalPresentationStyle = .popover
        let popover = webViewVC.popoverPresentationController!
        //popover.delegate = webViewVC
        popover.permittedArrowDirections = .up
        webViewVC.loadView()
        self.present(webViewVC, animated: true, completion: nil)
        webViewVC.showWebView()
    }

此代码实例化 webviewVC 并开始加载数据,但仅在 10 秒预取时间后显示。 showWebView() 方法很简单

func showWebView() {
    view.addSubview(webView)
}
  1. 您可以使用@AshleyMills 的回答在数据获取完成后加载 webView 或
  2. 您可以在延迟一段时间(在我的示例中为 10 秒)或
  3. 后加载 webView
  4. 您可以通过将 DispatchQueue.main.asyncAfter() 中的所有代码更改为按钮操作来将页面加载为操作(例如,单击按钮)。潜在客户完成后,您可以在此处使用@AshleyMills 代码启用按钮。

干杯!