OAuthSwift WKWebView открывается и закрывается в постоянном цикле - PullRequest
0 голосов
/ 28 ноября 2018

Я пытаюсь аутентифицировать приложение iOS с помощью API Spotify, используя OAuth2.Для этого я использую 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 голосов
/ 28 ноября 2018

Вы ничего не делаете для изменения состояния вашего приложения.Из-за этого initAuthFlow вызывается снова, я полагаю, что Spotify имеет действительный сеанс для вас, поэтому контроллер отключается и цикл повторяется.

В случае успешного завершения вашего вызова oauthSwift.authorize вы должны поставитьтокены в KeyChain или где-нибудь в безопасности и убедитесь, что initAuthFlow вызывается только тогда, когда это состояние недопустимо.

...