【问题标题】:Load ViewController's WebView before showing在显示之前加载 ViewController 的 WebView
【发布时间】:2018-09-10 12:36:09
【问题描述】:

我有一个带有包含 WebView 的 ViewController 的应用程序。因为 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,然后实例化if let c = webViewVC.childViewControllers[0] as? WebViewController。 webViewVC 不是 WebViewController?是否在点击按钮时调用此代码?请您提供更多背景信息吗?
  • 我相信你可以做这样的事情的唯一地方就是在viewWillAppear() 中做。至于在应用程序启动时加载 VC,无论如何都会执行此操作,前提是您输入的视图是指示为“初始视图控制器”的视图。此视图在调用viewDidLoad() 时在启动屏幕阶段加载。除了在 AppDelegate 中执行一些操作。但是我不建议这样做,因为该应用程序可能尚未完全加载。

标签: ios swift uiviewcontroller wkwebview


【解决方案1】:

您的问题并不完全清楚,但我假设您正在从另一个视图控制器展示您的 Web 视图控制器,例如按下按钮。像这样的……

您需要做的是异步处理。

  • 实例化您的网络视图控制器
  • 开始加载其网页视图
  • 等待完成
  • 展示 Web 视图控制器

例子……

WebViewController

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)
        }
    }
}

【讨论】:

  • 我真的不知道今天早上我怎么想不到把它放到一个非本地函数中。非常感谢,抱歉浪费你的时间哈哈哈我现在觉得很愚蠢
  • 感谢您的回答 Ashley Mills,这正是我想要的,我需要一个简单的 Web 容器,但由于页面太大,加载需要时间,这段代码显示了我的启动画面,直到页面完全加载。我在网页的第一个屏幕中加载透明胶片时遇到问题,但我会为此提出一个新问题。非常感谢。
【解决方案2】:

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

案例一:webViewVC 是启动后的第一个 VC

这里,我们可以获得的最大“预取”时间是我们在调用方法 application:didFinishLaunchingWithOptions: 时获得的时间。假设这里执行的处理器繁重的进程不多,则不会有任何时间进行预取。所以唯一的选择是在 UI 中显示一个与 launchScreen 类似的屏幕,以便用户可能认为它是仍在加载的应用程序。 (我个人要做的是将启动屏幕制作为仅显示应用程序主题颜色的屏幕,并使用应用程序图标将我的第一个屏幕设置为启动屏幕;提供更好的专业方法,也有足够的时间让我让事情滚动)

案例2:webViewVC不是第一个VC

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

使用 DUMMY 启动屏幕加载 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 秒)后加载 webView 或
  3. 您可以通过将DispatchQueue.main.asyncAfter() 中的所有代码更改为按钮操作来将页面加载为操作(例如,单击按钮)。在这里,您可以使用@AshleyMills 代码在线索完成后启用该按钮。

干杯!

【讨论】:

    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多