SwiftUI中调用OID认证方法时如何将View转为UIViewController?
解决SwiftUI视图转换为UIViewController用于OIDAuthState认证的问题
SwiftUI的View是结构体类型,和UIKit的UIViewController分属不同框架体系,直接传入MainView实例必然会出现类型不匹配错误。你需要获取当前SwiftUI视图所在的UIKit容器控制器,以下是两种可行方案:
方案一:通过UIApplication获取顶层ViewController
给UIApplication编写扩展,用来获取当前应用的顶层可见ViewController:
extension UIApplication { func topViewController(controller: UIViewController? = UIApplication.shared.keyWindow?.rootViewController) -> UIViewController? { if let navigationController = controller as? UINavigationController { return topViewController(controller: navigationController.visibleViewController) } if let tabController = controller as? UITabBarController { if let selected = tabController.selectedViewController { return topViewController(controller: selected) } } if let presented = controller?.presentedViewController { return topViewController(controller: presented) } return controller } }
在MainView中调用该方法获取顶层VC,替换原代码中错误的vc实例:
struct MainView: View { var body: some View { // 示例:在按钮点击事件中触发认证 Button("发起认证") { guard let topVC = UIApplication.shared.topViewController() else { print("无法获取顶层ViewController") return } // 确保request已正确初始化 appDelegate.currentAuthorizationFlow = OIDAuthState.authState(byPresenting: request, presenting: topVC) { authState, error in if let authState = authState { print("获取到授权令牌. Access token: \(authState.lastTokenResponse?.accessToken ?? "nil")") } else { print("授权错误: \(error?.localizedDescription ?? "未知错误")") } } } } }
方案二:自定义UIHostingController并传递引用
如果需要更精准控制当前视图的容器控制器,可以在App入口处自定义UIHostingController,并将其引用传递给SwiftUI视图:
- 在App入口(
@main结构体)中保存UIHostingController引用:
@main struct YourApp: App { @State private var hostingVC: UIViewController? var body: some Scene { WindowGroup { MainView(hostingVC: $hostingVC) .onAppear { hostingVC = UIApplication.shared.topViewController() } } } }
- 在
MainView中接收引用并使用:
struct MainView: View { @Binding var hostingVC: UIViewController? var body: some View { Button("发起认证") { guard let vc = hostingVC else { return } appDelegate.currentAuthorizationFlow = OIDAuthState.authState(byPresenting: request, presenting: vc) { authState, error in if let authState = authState { print("获取到授权令牌. Access token: \(authState.lastTokenResponse?.accessToken ?? "nil")") } else { print("授权错误: \(error?.localizedDescription ?? "未知错误")") } } } } }
关键修正点
你原代码中的let vc = MainView()是错误写法,MainView是SwiftUI视图结构体,并非UIViewController实例,必须替换为上述方案中获取的UIKit控制器实例。
内容的提问来源于stack exchange,提问作者Alexander Paul
相关产品推荐
相关产品推荐

