我想在SwiftUI视图层次结构中显示WKWebView,并且想使用SwiftUI中实现的按钮控制WKWebView。
我可以通过创建一个实现WebView
并包装UIViewRepresentable
的SwiftUI WKWebView
类来实现此目的,
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
}
}
当用户点击按钮时,我想以某种方式调用goBack
上的WKWebView
。我该如何在SwiftUI中惯用的方式?
我认为这种方法要么很脆弱,要么不是惯用的SwiftUI ...
表示用户在绑定中单击“返回”的次数。让WebView监听该绑定,并在绑定增加时移回。
已BrowserView
创建了一个名为MutableWebViewAPI
的对象,并将其传递给WebView
。 WebView
侦听此对象,以便当BrowserView
调用类似MutableWebViewAPI.goBack()
的对象时,WebView
会执行相同的操作。
答案 0 :(得分:1)
我认为最好的方法是通过在父视图上创建一个PassthroughSubject
然后订阅孩子WebView
中的事件来利用Combine的功能。
首先,在您的UIViewReprsentable
中创建一个结构,以捕获要发送到WebView
的可用事件:
struct WebView: UIViewReprsentable {
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())
}
}
}