OAuthSwift WKWebView以恒定循环打开和关闭

时间:2018-11-28 07:14:28

标签: ios swift wkwebview

我正在尝试使用OAuth2通过Spotify API对iOS应用进行身份验证。 为此,我正在使用OAuthSwift

加载我的应用程序后,我将重定向到Spotify,我可以登录并允许我的应用程序访问我的帐户。

但是,当我重定向回我的应用程序时,WebView被关闭了,但是立即在前一页上重新打开,关闭了它并重新打开。

这将无限期地继续循环。

我想知道这是否与在initAuthFlow中调用我的viewDidAppear函数有关,但是将其移至viewDidLoad会引起抱怨

Warning: Attempt to present <OAuthKeyChainApp.WKWebViewController: 0x7fb42b505160> on <OAuthKeyChainApp.HomeController: 0x7fb42b50cf30> whose view is not in the window hierarchy!

并且永远不会显示控制器。

HomeController.swift

class HomeController: OAuthViewController {

    let oauthSwift = OAuth2Swift(
        consumerKey: "xxxxxx",
        consumerSecret: "xxxxxx",
        authorizeUrl: "https://accounts.spotify.com/en/authorize",
        accessTokenUrl: "https://accounts.spotify.com/api/token",
        responseType: "code"
    )

    lazy var internalWebViewController: WKWebViewController = {
        let controller = WKWebViewController()
        controller.view = UIView(frame: UIScreen.main.bounds)
        controller.loadView()
        controller.viewDidLoad()
        return controller
    }()

    override func viewDidLoad() {
        super.viewDidLoad()

        view.backgroundColor = .purple
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)

        initAuthFlow()
    }

    fileprivate func initAuthFlow() -> Void {

        oauthSwift.authorizeURLHandler = internalWebViewController

        guard let callbackURL = URL(string: "oauthkeychainapp://oauthkeychain-callback") else { return }

        oauthSwift.authorize(
            withCallbackURL: callbackURL,
            scope: "user-library-modify",
            state: generateState(withLength: 20),
            success: { (credential, response, params) in
                print(credential)
            }) { (error) in
            print(error.localizedDescription)
        }
    }
}

extension HomeController: OAuthWebViewControllerDelegate {
    func oauthWebViewControllerDidPresent() { }
    func oauthWebViewControllerDidDismiss() { }
    func oauthWebViewControllerWillAppear() { }
    func oauthWebViewControllerDidAppear() { }
    func oauthWebViewControllerWillDisappear() { }
    func oauthWebViewControllerDidDisappear() { oauthSwift.cancel() }
}

WKWebViewController.swift

import UIKit
import WebKit
import OAuthSwift

class WKWebViewController: OAuthWebViewController {
    var webView: WKWebView!
    var targetURL: URL?

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

    override func handle(_ url: URL) {
        targetURL = url
        super.handle(url)
        loadAddressURL()
    }

    func loadAddressURL() {
        guard let url = targetURL else { return }
        let req = URLRequest(url: url)

        self.webView?.load(req)
    }
}

extension WKWebViewController: WKUIDelegate, WKNavigationDelegate {
    override func loadView() {
        let webConfiguration = WKWebViewConfiguration()
        webView = WKWebView(frame: .zero, configuration: webConfiguration)
        webView.allowsBackForwardNavigationGestures = true
        webView.uiDelegate = self
        webView.navigationDelegate = self
        view = webView
    }

    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        print("loaded")
    }

    func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
        // Check for OAuth Callback
        if let url = navigationAction.request.url, url.scheme == "oauthkeychainapp" {
            UIApplication.shared.open(url, options: [:], completionHandler: nil)
            self.dismiss(animated: true, completion: nil)
            decisionHandler(.cancel)
            return
        }

        // Restrict URL's a user can access
        if let host = navigationAction.request.url?.host {
            if host.contains("spotify") {
                decisionHandler(.allow)
                return
            } else {
                // open link outside of our app
                UIApplication.shared.open(navigationAction.request.url!)
                decisionHandler(.cancel)
                return
            }
        }

        decisionHandler(.cancel)

    }
}

1 个答案:

答案 0 :(得分:1)

您没有做任何更改应用程序状态的操作。由于此initAuthFlow被再次调用,因此我认为Spotify为您提供了一个有效的会话,因此控制器被关闭,循环重复。

在成功完成oauthSwift.authorize调用后,应将令牌放入KeyChain或安全的地方,并确保仅在该状态无效时才调用initAuthFlow