可以从SwiftUI使用ASWebAuthenticationSession吗?

时间:2019-10-26 19:44:26

标签: swift xcode authentication swiftui

我想使用ASWebAuthenticationSession针对OAuth API进行身份验证,但是它似乎无法从SwiftUI使用。 这就是我想要的:

struct ContentView: View: ASWebAuthenticationPresentationContextProviding {
    var body: some View {
        NavigationView {
            VStack {
                Button("Hello World", {
                    // Run oauth flow
                }
            }
        }
        .navigationBarTitle(Text("Greed of Savin"))
        .navigationViewStyle(StackNavigationViewStyle())
    }

    func presentationAnchor(for session: ASWebAuthenticationSession) -> ASPresentationAnchor {
        return BungieApi.sharedInstance.presentationAnchor ?? ASPresentationAnchor()
    }
}

}

它需要采用与SwiftUI的视图不兼容的协议ASWebAuthenticationPresentationContextProviding

我可以通过重定向到ViewController来解决这个问题,该ViewController随后可以提供ASWebAuthenticationPresentationContextProviding,但这又增加了一个额外的视图/导航步骤。

有什么方法可以通过SwiftUI使用ASWebAuthenticationSession而不放入ViewController中吗?

2 个答案:

答案 0 :(得分:0)

我分三个部分解决了这个问题:

首先,在SceneDelegate.swift中进行设置期间,在全局对象中捕获窗口:

var globalPresentationAnchor: ASPresentationAnchor? = nil
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        // ...            
        globalPresentationAnchor = window
    }
}

然后,创建一个小的ViewController,以将窗口对象提供给使用ASWebAuthenticationSession的人:

class ShimViewController: UIViewController, ASWebAuthenticationPresentationContextProviding
{
    func presentationAnchor(for session: ASWebAuthenticationSession) -> ASPresentationAnchor {
        // Perhaps I don't need the window object at all, and can just use:
        // return ASPresentationAnchor()
        return globalPresentationAnchor ?? ASPresentationAnchor()
    }
}

最后,调用身份验证API,将ShimViewController作为演示者。

    let session = ASWebAuthenticationSession(/**/)
    session.presentationContextProvider = ShimViewController()
    session.start()

答案 1 :(得分:0)

使用 BetterSafariView ,可以使用ASWebAuthenticationSession而不用钩住SceneDelegate在SwiftUI中。

import SwiftUI
import BetterSafariView

struct ContentView: View {
    
    @State private var startingWebAuthenticationSession = false
    
    var body: some View {
        Button("Start WebAuthenticationSession") {
            self.startingWebAuthenticationSession = true
        }
        .webAuthenticationSession(isPresented: $startingWebAuthenticationSession) {
            WebAuthenticationSession(
                url: URL(string: "https://github.com/login/oauth/authorize?client_id=\(clientID)")!,
                callbackURLScheme: "myapp"
            ) { callbackURL, error in
                print(callbackURL, error)
            }
        }
    }
}