Search code examples
uiviewcontrollerswift3uiwebviewdelegate

Swift 3. Can present a UIViewController with UIWebViewDelegate but not push it


I have a UIViewController with UIWebViewDelegate. I found that I can present it just fine but not push it. If I try to push it the target view controller loads and executes any variables set but does not fire viewDidLoad() and instead just returns to my calling menu view controller without error.

I set a breakpoint on the first var declaration after the class and stepped through the code. When it got to webView init it flashed up the home (not target) view controller in the simulator and then continued though the var declarations before returning back to my home view controller.

Here is my menu code

works:

let myWebViewController = MyWebViewController()

myWebViewController.urlString = "myUrl"

present(myWebViewController, animated: true, completion: nil)

does not work

let myWebViewController = MyWebViewController()

myWebViewController.urlString = "myUrl"

let navController = (UIApplication.shared.delegate as! AppDelegate).navController

navController!.pushViewController(myWebViewController, animated: true)

Here is my redacted target view controller code. The URL to load is set in the menu.

import UIKit

class MyWebViewController: UIViewController, UIWebViewDelegate {

var urlString: String = "invalid url"

var url: URL {
    return URL(string: urlString)!
}

var urlRequest: URLRequest {

    var urlRequest = URLRequest(url: url)

    return urlRequest
}

let webView: UIWebView = {
    let view = UIWebView()
    view.backgroundColor = .white
    view.translatesAutoresizingMaskIntoConstraints = false
    return view
}()

// declare various buttons and stack views 

override func viewDidLoad() {
    super.viewDidLoad()

    webView.delegate = self

    contentStackView.addArrangedSubview(webView)

    mainStackView.addArrangedSubview(contentStackView)

    view.addSubview(mainStackView)
}

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(true)

    webView.loadRequest(urlRequest as URLRequest)
}

Solution

  • The problem has nothing to do with the web view, the web view controller, or anything else except where you're pushing the view controller. You are saying:

    let navController = (UIApplication.shared.delegate as! AppDelegate).navController
    navController!.pushViewController(myWebViewController, animated: true)
    

    That is highly unusual. The usual thing is that we are inside a navigation interface already, and we push onto its stack:

    let navController = self.navigationController
    navController!.pushViewController(myWebViewController, animated: true)
    

    But you are not saying that. Why not? I'm guessing it's because self does not have a navigationController. So you are successfully pushing onto the navigation controller, all right, but you are not seeing anything happening because the navigation controller is behind the scenes — the self view controller's view is blocking it or has replaced it.

    And that explains why you never detect the url loading. Your call to webView.loadRequest is in viewWillAppear. But this view will not appear; it is behind the scenes. viewWillAppear is never called. Similarly viewDidLoad is not called, because this view is not going to load; the navigation controller is not occupying the interface — self is.