SwiftUI 和 UIKit 与旧 API 中的 UIViewController 要求交互

Posted

技术标签:

【中文标题】SwiftUI 和 UIKit 与旧 API 中的 UIViewController 要求交互【英文标题】:SwiftUI and UIKit interfacing with UIViewController requirements in older APIs 【发布时间】:2019-06-07 00:43:39 【问题描述】:

场景:

我有一个简单的 SwiftUI 视图,如下所示:

struct AuthView: View 
    var body: some View 
        VStack 
            Button(action: handleLogin) 
                Text("Login to twitter")
            
        
    

    private func handleLogin() 
        // do login stuff here
    

现在,理想情况下,在 handleLogin 函数中,我只需执行 OAuth 请求并处理登录等。但是,我正在使用我在 GitHub 上找到的库来进行演示。

这个库有一个方法authorize(callBackUrl: URL, presentingController: UIViewController),当被调用时会显示一个允许用户登录到twitter的safari控制器。但是,要调用authorize,您需要传入一个符合SFSafariViewControllerDelegate 的控制器。从我目前的基本理解来看,SwiftUI 中的View 类型不是视图控制器,而且由于它是一个结构,因此不能符合SFSafariViewControllerDelegate

我查看了 Apples 网站上的 Interfacing with UIKit 教程,他们似乎创建了一个 UIViewControllerRepresentable 类型,然后从 View 类型返回此“控制器”在 bodyView 中。这允许他们使用 UIKit 中的 PageViewController。但是,这并不完全是我拥有或需要的用例。我只需要能够以某种方式将我的简单View 转换为UIViewControllerUIHostingController 会在这里使用吗?如果是,如何注入这种依赖关系,或者视图是否应该知道/使用控制器?

我的困惑主要在于还不知道 SwiftUI 的最佳实践是什么。 View 类型似乎取代了 UIKit 中 UIViewController 的使用,但是在与 UIKit 接口时转换是如何工作的呢?

如果有人有任何想法或想讨论这个问题,我将不胜感激!谢谢。

【问题讨论】:

可能这是你正在使用的库需要更改的情况;它需要UIViewController 还是需要SFSafariViewControllerDelegate?当它只需要后者时,却要求前者符合后者,这可能是一个糟糕的设计。 【参考方案1】:

我很确定有更好的方法来解决这个问题,但您可能会从以下内容中获得灵感。

只是给你一些背景。我正在创建一个快速原型来实现 Uber 授权,我是这样实现的:

//
//  ContentView.swift
// 
//  Created by Daniel Tello on 05/11/19.
//  Copyright © 2019 Daniel Tello. All rights reserved.
//

import SwiftUI
import UberCore

struct ContentView: View 
    var body: some View 
        VStack 
            Button(action: uberLogin) 
            Text("Uber")
            
        
    


func uberLogin() 
    let scopes: [UberScope] = [.profile, .places, .request]
    let presentingView = UIApplication.shared.windows.last?.rootViewController
    let loginManager = LoginManager(loginType: .native)

    loginManager.login(requestedScopes: scopes, presentingViewController: presentingView)  (accessToken, error) -> () in
        if accessToken != nil 
           NSLog("Got an AccessToken!")
         else 
            // Error
            if let error = error 
                NSLog(error.localizedDescription)
             else 
                NSLog("An Unknown Error Occured")
            
        
    



struct ContentView_Previews: PreviewProvider 
    static var previews: some View 
        ContentView()
    


【讨论】:

以上是关于SwiftUI 和 UIKit 与旧 API 中的 UIViewController 要求交互的主要内容,如果未能解决你的问题,请参考以下文章

将 AppKit/UIKit 中的 Key-Value Observation 转换为 Combine 和 SwiftUI

SwiftUI/UIKit 如何将 SwiftUI 字体转换为 UIKit UIFont?

如何从内部的 SwiftUI 视图返回到 UIKit?

SwiftUI 小部件中的 UIKit UserDefaults

在SwiftUI项目中使用UIKit(SwiftUI和UIKit混合开发)

从 UIKit 调整 SwiftUI 组件