title: WKWebView delegate not responding to delegate method call
body: <p>I have a WKWebView that is used to present the login screen of my OAuth Identity provider. </p>
  
  <pre><code>import UIKit
  import WebKit
  
  protocol OAuth2WKWebViewDelegate: class {
      func didReceiveAuthorizationCode(_ code: String) -&gt; Void
      func didRevokeSession() -&gt; Void
  }
  
  class OAuth2WKWebViewController: UIViewController {
      let targetUrl: URLComponents
      let webView = WKWebView()
  
      weak var delegate: OAuth2WKWebViewDelegate?
  
      init(targetUrl: URLComponents) {
          self.targetUrl = targetUrl
          super.init(nibName: nil, bundle: nil)
      }
  
      required init?(coder aDecoder: NSCoder) {
          fatalError("init(coder:) has not been implemented")
      }
  
      override func viewDidLoad() {
          super.viewDidLoad()
          loadUrl()
      }
  }
  
  extension OAuth2WKWebViewController: WKNavigationDelegate {
      func loadUrl() {
          guard let url = targetUrl.url else { return }
  
          view = webView
          webView.load(URLRequest(url: url))
          webView.allowsBackForwardNavigationGestures = true
          webView.navigationDelegate = self
      }
  
      func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -&gt; Void) {
          if let url = navigationAction.request.url {
              if url.scheme == "appdev", url.absoluteString.range(of: "code") != nil {
                  let urlParts = url.absoluteString.components(separatedBy: "?")
                  let code = urlParts[1].components(separatedBy: "code=")[1]
                  delegate?.didReceiveAuthorizationCode(code)
              }
  
              if url.absoluteString == "appdev://oauth-callback-after-sign-out" {
                  delegate?.didRevokeSession()
              }
          }
          decisionHandler(.allow)
      }
  }
  </code></pre>
  
  <p>I also have an IdentityService I use to present this view and respond to it's success / error.</p>
  
  <pre><code>protocol IdentityServiceProtocol {
      var hasValidToken: Bool { get }
      func initAuthCodeFlow() -&gt; Void
      func renderOAuthWebView(forService service: IdentityEndpoint, queryitems: [String: String]) -&gt; Void
      func storeOAuthTokens(accessToken: String, refreshToken: String, completion: @escaping () -&gt; Void) -&gt; Void
      func renderAuthView() -&gt; Void
  }
  
  class IdentityService: IdentityServiceProtocol {
  
      fileprivate var apiClient: APIClient
      fileprivate var keyChainService: KeyChainService
  
      init(apiClient: APIClient = APIClient(), keyChainService: KeyChainService = KeyChainService()) {
          self.apiClient = apiClient
          self.keyChainService = keyChainService
      }
  
      var hasValidToken: Bool {
          return keyChainService.fetchSingleObject(withKey: "AccessToken") != nil
      }
  
      func initAuthCodeFlow() -&gt; Void {
          let queryItems = ["response_type": "code", "client_id": clientId, "redirect_uri": redirectUri, "state": state, "scope": scope]
          renderOAuthWebView(forService: .auth(company: "benefex"), queryitems: queryItems)
      }
  
      func initRevokeSession() -&gt; Void {
          guard let refreshToken = keyChainService.fetchSingleObject(withKey: "RefreshToken") else { return }
          let queryItems = ["refresh_token": refreshToken]
          renderOAuthWebView(forService: .revokeSession(company: "benefex"), queryitems: queryItems)
      }
  
      func renderOAuthWebView(forService service: IdentityEndpoint, queryitems: [String: String]) -&gt; Void {
          guard let targetUrl = constructURLComponents(endPoint: service, queryItems: queryitems) else { return }
          let webView = OAuth2WKWebViewController(targetUrl: targetUrl)
          webView.delegate = self
          UIApplication.shared.windows.first?.rootViewController = webView
      }
  
      func storeOAuthTokens(accessToken: String, refreshToken: String, completion: @escaping ()-&gt; Void) -&gt; Void {
          let success = keyChainService.storeManyObjects(["AccessToken": accessToken, "RefreshToken": refreshToken])
          guard success == true else { return }
          completion()
      }
  
      func renderAuthView() -&gt; Void {
          UIApplication.shared.windows.first?.rootViewController = UINavigationController.init(rootViewController: AuthenticatedViewController())
      }
  }
  
  extension IdentityService: OAuth2WKWebViewDelegate {
      func didReceiveAuthorizationCode(_ code: String) {
          apiClient.call(endpoint: IdentityEndpoint.accessToken(company: "benefex", code: code)) { [weak self] (response: OAuthTokenResponse) in
              switch response {
              case .success(let payload):
                  guard let accessToken = payload.accessToken, let refreshToken = payload.refreshToken else { return }
                  self?.storeOAuthTokens(accessToken: accessToken, refreshToken: refreshToken) { self?.renderAuthView() }
              case .error:
                  // login failed for some reason
                  print("could not complete request for access token")
              }
          }
      }
  
      func didRevokeSession() {
          print("This was called")
      }
  }
  
  extension IdentityService {
      fileprivate var state: String {
          return generateState(withLength: 20)
      }
  
      fileprivate func constructURLComponents(endPoint: IdentityEndpoint, queryItems: [String: String]) -&gt; URLComponents? {
          var url = URLComponents(url: endPoint.baseUrl, resolvingAgainstBaseURL: false)
          url?.path = endPoint.path
          url?.queryItems = queryItems.map { URLQueryItem(name: $0.key, value: $0.value) }
  
          return url
      }
  
      fileprivate func generateState(withLength len: Int) -&gt; String {
          let letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
          let length = UInt32(letters.count)
  
          var randomString = ""
          for _ in 0..&lt;len {
              let rand = arc4random_uniform(length)
              let idx = letters.index(letters.startIndex, offsetBy: Int(rand))
              let letter = letters[idx]
              randomString += String(letter)
          }
          return randomString
      }
  }
  
  extension IdentityService {
      var clientId: String {
          let envVar = ProcessInfo.processInfo.environment
          guard let value = envVar["APP_CLIENT_ID"] else { fatalError("Missing APP_CLIENT_ID enviroment variable") }
          return value
      }
  
      var redirectUri: String {
          let envVar = ProcessInfo.processInfo.environment
          guard let value = envVar["APP_REDIRECT_URI"] else { fatalError("Missing APP_REDIRECT_URI enviroment variable") }
          return value
      }
  
      var scope: String {
          let envVar = ProcessInfo.processInfo.environment
          guard let value = envVar["APP_SCOPES"] else { fatalError("Missing APP_SCOPES enviroment variable") }
          return value
      }
  }
  </code></pre>
  
  <p>The <code>delegate?.didReceiveAuthorizationCode(code)</code> is working.</p>
  
  <p>However when <code>delegate?.didRevokeSession()</code> is called from the WebView, the identity service does not respond.</p>
  
  <p>I added some console logs and can see my IdentityService is being de - init when I invoke the logout method.</p>
  
  <p>I believe this is causing it to do nothing when the delegate method fires.</p>
  
  <p>How can I ensure the delegate method is called still?</p>