在 SwiftUI 中从 UIViewController 调用函数
Posted
技术标签:
【中文标题】在 SwiftUI 中从 UIViewController 调用函数【英文标题】:Calling functions from UIViewController in SwiftUI 【发布时间】: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()
引用的实例不是显示的实例。
如何获取显示的具体实例?
【问题讨论】:
【参考方案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
这里发生了什么:
VCLink
是一个 ObservableObject
,我用作在视图之间进行通信的中间人
ContentView
具有对 VCLink
的引用——当按下按钮时,VCLink
上的 Publisher
会将其传达给任何订阅者
当VCRepresented
被创建/更新时,我在它的Coordinator
中存储了对ViewController 和VCLink
的引用
Coordinator
采用Publisher
并在其sink
方法中对存储的ViewController
执行操作。在这个演示中,我只是打印动作。在您的示例中,您希望触发照片本身。
【讨论】:
以上是关于在 SwiftUI 中从 UIViewController 调用函数的主要内容,如果未能解决你的问题,请参考以下文章
如何在 SwiftUI 中从 FetchedResults (CoreData) 中获取 NSOrderedSet
在 SwiftUI 中从 Observable 视图模型初始化 Map