在 SwiftUI 中控制嵌套 UIView 的惯用方法是什么



我想在 SwiftUI 视图层次结构中显示 WKWebView,我想使用 SwiftUI 中实现的按钮来控制 WKWebView。

我可以通过创建一个实现UIViewRepresentable并包装WKWebView的 SwiftUIWebView类来做到这一点,就像这样......

struct WebView: UIViewRepresentable {
func makeUIView(context: UIViewRepresentableContext<WebView>) -> WKWebView {
return WKWebView(frame: .zero)
}
func updateUIView(_ uiView: WKWebView, context: UIViewRepresentableContext<WebView>) {
// Update WKWebView here if necessary
}
}

。然后按如下方式使用它...


struct BrowserView: View {
var body: some View {
VStack {
WebView()
// Footer
HStack {
Button(action: {
// When this is called, I want to somehow call .goBack()
// on the WKWebView.
}) {
Image(systemName: "chevron.left")
}
...
} // HStack
} // VStack
}
}

当用户点击按钮时,我想以某种方式在WKWebView上调用goBack。我该如何在 SwiftUI 中习惯性地做到这一点?

我认为我认为要么很脆弱,要么不是惯用的 SwiftUI 的方法......

  • 表示用户在绑定中单击"后退"的次数。让 WebView 侦听该绑定,并在该绑定递增时向后移动。

  • BrowserView创建一个名为类似MutableWebViewAPI的对象,并将其传递给构造WebViewWebView侦听这个对象,以便当BrowserView调用类似MutableWebViewAPI.goBack()的东西时,WebView也会这样做。

我认为最好的方法是通过在父视图上创建一个PassthroughSubject来利用 Combine 的强大功能,然后订阅子WebView中的事件。

首先,在UIViewReprsentable中创建一个结构,用于捕获要发送到WebView的可用事件:

struct WebView: UIViewRepresentable {
enum WebEvent {
case back
case forward
}
let eventPublisher: AnyPublisher<WebEvent, Never>
init(eventPublisher: AnyPublisher<WebEvent, Never>) {
self.eventPublisher = eventPublisher
eventPublisher.sink { event in
// forward the appropriate event to your underlying WKWebView
}
}
}

接下来,在父级中创建PassthroughSubject以创建这些事件。

struct ParentView: View {
private let eventSender = PassthroughSubject<WebView.WebEvent, Never>()
var body: some View {
VStack {
Button("Back") {
self.eventSender.send(.back)
}
Button("Forward") {
self.eventSender.send(.forward)
}
WebView(eventPublisher: eventSender.eraseToAnyPublisher())
}
}
}

相关内容

最新更新