在 SwiftUI 中从 UIViewController 调用函数 [英] Calling functions from UIViewController in SwiftUI
问题描述
我希望从 Swift UI 管理的按钮调用 UIKit UIViewController 中的函数
I'm looking to call a function inside a UIKit UIViewController from a button managed by Swift UI
在我的 Swift UI 视图中,我有:
In my Swift UI View I have:
struct CameraView: View {
var body: some View {
cameraViewController = CameraViewController()
...
我看到它创建了两个实例,一个像调用任何类一样直接创建,另一个由 Swift UI 管理 UIKit UIViewControllers 所需的 makeUIViewController
方法创建.
which I see creates two instances, one directly created just like calling any class, and the other created by the required makeUIViewController
method needed for Swift UI to manage UIKit UIViewControllers.
但是,当我将一个函数附加到我的 Swift UI 中的按钮时,说,cameraViewController.takePhoto()
引用的实例不是显示的实例.
However when I attached a function to a button in my Swift UI say, cameraViewController.takePhoto()
The instance that is referenced is not the one displayed.
如何获取显示的具体实例?
How can I obtain the specific instance that is displayed?
推荐答案
这个问题可能有多种解决方案,但无论如何,您需要找到一种方法来保持对 <代码>UIViewController.因为 SwiftUI 视图本身是非常短暂的,您不能只在视图本身中存储引用,因为它可以随时重新创建.
There are probably multiple solutions to this problem, but one way or another, you'll need to find a way to keep a reference to or communicate with the UIViewController
. Because SwiftUI views themselves are pretty transient, you can't just store a reference in the view itself, because it could get recreated at any time.
要使用的工具:
ObservableObject -- 这将使您可以将数据存储在类而不是结构中,并且可以更轻松地存储引用、连接数据等
ObservableObject -- this will let you store data in a class instead of a struct and will make it easier to store references, connect data, etc
Coordinator -- 在 UIViewRepresentable
中,你可以使用 Coordinator 模式,它允许你存储对 UIViewController
的引用并与之通信
Coordinator -- in a UIViewRepresentable
, you can use a Coordinator pattern which will allow you to store references to the UIViewController
and communicate with it
Combine Publishers -- 这些是完全可选的,但我选择在这里使用它们,因为它们是一种无需太多样板代码即可轻松移动数据的方法.
Combine Publishers -- these are totally optional, but I've chosen to use them here since they're an easy way to move data around without too much boilerplate code.
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 和 Coordinator
接受Publisher
并在其sink
方法中对存储的ViewController
执行操作.在这个演示中,我只是打印动作.在您的示例中,您希望触发照片本身.
VCLink
的引用VCLink
is anObservableObject
that I'm using as a go-between to communicate between views- The
ContentView
has a reference to theVCLink
-- when the button is pressed, thePublisher
onVCLink
communicates that to any subscribers - When the
VCRepresented
is created/updated, I store a reference to the ViewController and theVCLink
in itsCoordinator
- The
Coordinator
takes thePublisher
and in itssink
method, performs an action on the storedViewController
. In this demo, I'm just printing the action. In your example, you'd want to trigger the photo itself.
这篇关于在 SwiftUI 中从 UIViewController 调用函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!