Joh*_*n M 5 viewcontroller ios swiftui
我已经到处寻找这个问题的答案,但似乎找不到。如何从 swiftUI 调用 viewController 方法(例如单击按钮)?
我有一个看起来像这样的视图控制器:
import Player
class PlayerViewController: UIViewController {
var player = Player()
func play() {
self.player.play()
}
}
Run Code Online (Sandbox Code Playgroud)
我有一个看起来像这样的包装:
import SwiftUI
import AVFoundation
struct ProjectEditorPlayerBridge: UIViewControllerRepresentable {
func makeUIViewController(context: Context) -> PlayerViewController {
let player = PlayerViewController()
return player
}
func updateUIViewController(_ uiViewController: PlayerViewController, context: Context) {
}
typealias UIViewControllerType = PlayerViewController
}
Run Code Online (Sandbox Code Playgroud)
我希望能够在 swiftUI 中使用按钮操作并调用 viewControllerplay方法一次。我已经看到建议在包装器上设置状态/绑定并调用 updateUIViewController 中的方法的答案,但是当我这样做时,我看到它被调用多次,而不仅仅是一次。
这是可能的基于协议/配置器的方法,它允许直接使用从代码简单性和可读性来看更合适的操作。
protocol Player { // use protocol to hide implementation
func play()
}
class PlayerViewController: UIViewController, Player {
var player = Player()
func play() {
self.player.play()
}
}
struct ProjectEditorPlayerBridge: UIViewControllerRepresentable {
var configurator: ((Player) -> Void)? // callback
func makeUIViewController(context: Context) -> PlayerViewController {
let player = PlayerViewController()
// callback to provide active component to caller
configurator?(player)
return player
}
func updateUIViewController(_ uiViewController: PlayerViewController, context: Context) {
}
typealias UIViewControllerType = PlayerViewController
}
struct DemoPlayerView: View {
@State private var player: Player? // always have current player
var body: some View {
VStack {
ProjectEditorPlayerBridge { self.player = $0 } // << here !!
// use player action directly !!
Button("Play", action: player?.play ?? {})
}
}
}
Run Code Online (Sandbox Code Playgroud)
好问题。在我看来,SwiftUI 这里缺少一些东西。
如果您的应用程序中只有这些视图控制器之一,那么您可以通过使用全局PassthroughSubject(或传递事件的其他方式)来解决此问题。您UIViewController可以订阅它,您的 SwiftUI 代码可以向它发布点击。
如果您不想这样做,这里有另一种解决方法,用于UUID消除您提到的多次调用。
也许我们会在 WWDC 2020 上看到新的选择。
struct ContentView: View {
@State var buttonClickID: UUID? = nil
var body: some View {
VStack {
Button(action: self.callPlay) { Text("Play") }
ProjectEditorPlayerBridge(clickID: $buttonClickID)
}
}
func callPlay() {
buttonClickID = UUID()
}
}
struct ProjectEditorPlayerBridge: UIViewControllerRepresentable {
@Binding var clickID: UUID?
func makeUIViewController(context: Context) -> PlayerViewController {
let player = PlayerViewController()
return player
}
class Coordinator {
var previousClickID: UUID? = nil
}
func makeCoordinator() -> Coordinator {
return Coordinator()
}
func updateUIViewController(_ uiViewController: PlayerViewController, context: Context) {
print("Update")
if clickID != context.coordinator.previousClickID {
uiViewController.play()
context.coordinator.previousClickID = clickID
} else {
print("Not calling play")
}
}
typealias UIViewControllerType = PlayerViewController
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5889 次 |
| 最近记录: |