【问题标题】:Calling functions from UIViewController in SwiftUI在 SwiftUI 中从 UIViewController 调用函数
【发布时间】:2021-01-27 16:52:50
【问题描述】:

我希望通过 Swift UI 管理的按钮调用 UIKit UIViewController 中的函数

在我的 Swift UI 视图中,我有:

struct CameraView: View {
        var body: some View {
            cameraViewController = CameraViewController()
...

我看到它创建了两个实例,一个像调用任何类一样直接创建,另一个由 Swift UI 管理 UIKit UIViewControllers 所需的 makeUIViewController 方法创建。

但是,当我在 Swift UI 中将函数附加到按钮时,cameraViewController.takePhoto() 引用的实例不是显示的实例。

如何获取显示的具体实例?

【问题讨论】:

    标签: swiftui uikit


    【解决方案1】:

    这个问题可能有多种解决方案,但无论哪种方式,您都需要找到一种方法来保持对UIViewController 的引用或与之通信。因为 SwiftUI 视图本身是非常短暂的,所以您不能只在视图本身中存储一个引用,因为它可以随时重新创建。

    使用工具:

    • ObservableObject -- 这将使您可以将数据存储在 class 而不是结构中,并且可以更轻松地存储引用、连接数据等

    • 协调器 -- 在 UIViewRepresentable 中,您可以使用协调器模式,它允许您存储对 UIViewController 的引用并与之通信

    • Combine Publishers -- 这些是完全可选的,但我在这里选择使用它们,因为它们是一种无需太多样板代码即可轻松移动数据的方法。

    import SwiftUI
    import Combine
    
    struct ContentView: View {
        @ObservedObject var vcLink = VCLink()
        var body: some View {
            VStack {
                VCRepresented(vcLink: vcLink)
                Button("Take photo") {
                    vcLink.takePhoto()
                }
            }
        }
    }
    
    enum LinkAction {
        case takePhoto
    }
    
    class VCLink : ObservableObject {
        @Published var action : LinkAction?
        
        func takePhoto() {
            action = .takePhoto
        }
    }
    
    class CustomVC : UIViewController {
        func action(_ action : LinkAction) {
            print("\(action)")
        }
    }
    
    struct VCRepresented : UIViewControllerRepresentable {
        var vcLink : VCLink
        
        class Coordinator {
            var vcLink : VCLink? {
                didSet {
                    cancelable = vcLink?.$action.sink(receiveValue: { (action) in
                        guard let action = action else {
                            return
                        }
                        self.viewController?.action(action)
                    })
                }
            }
            var viewController : CustomVC?
            
            private var cancelable : AnyCancellable?
        }
        
        func makeCoordinator() -> Coordinator {
            return Coordinator()
        }
        
        func makeUIViewController(context: Context) -> CustomVC {
            return CustomVC()
        }
        
        func updateUIViewController(_ uiViewController: CustomVC, context: Context) {
            context.coordinator.viewController = uiViewController
            context.coordinator.vcLink = vcLink
        }
    }
    

    这里发生了什么:

    1. VCLink 是一个 ObservableObject,我用作在视图之间进行通信的中间人
    2. ContentView 具有对 VCLink 的引用——当按下按钮时,VCLink 上的 Publisher 会将其传达给任何订阅者
    3. VCRepresented 被创建/更新时,我在它的Coordinator 中存储了对ViewController 和VCLink 的引用
    4. Coordinator 采用Publisher 并在其sink 方法中对存储的ViewController 执行操作。在这个演示中,我只是打印动作。在您的示例中,您希望触发照片本身。

    【讨论】:

      猜你喜欢
      • 2020-02-16
      • 1970-01-01
      • 1970-01-01
      • 2020-04-01
      • 1970-01-01
      • 2022-01-22
      • 1970-01-01
      • 1970-01-01
      • 2020-12-19
      相关资源
      最近更新 更多