Можно ли использовать ASWebAuthenticationSession из SwiftUI?
Я хотел бы пройти аутентификацию по OAuth API, используяASWebAuthenticationSession
однако это не похоже на использование 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()
}
}
}
Требуется принятие протокола ASWebAuthenticationPresentationContextProviding
который несовместим с представлениями SwiftUI.
Я могу обойти это, перенаправив ViewController, который затем может предоставить ASWebAuthenticationPresentationContextProviding
, но это добавляет дополнительный шаг просмотра / навигации.
Есть ли способ использовать ASWebAuthenticationSession
из SwiftUI, не переходя в ViewController?
2 ответа
Я решил это в трех частях:
Сначала сделайте снимок окна в глобальном объекте во время настройки в 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()
Используя 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)
}
}
}
}