在SwiftUI中控制嵌套UIView的惯用方式是什么 [英] What's the idiomatic way to control a nested UIView in SwiftUI

查看:99
本文介绍了在SwiftUI中控制嵌套UIView的惯用方式是什么的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在SwiftUI视图层次结构中显示WKWebView,并且希望使用SwiftUI中实现的按钮控制WKWebView.

I want to show a WKWebView in a SwiftUI view hierarchy, and I want to control the WKWebView using buttons implemented in SwiftUI.

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

I can do this by creating a SwiftUI WebView class that implements UIViewRepresentable and wraps WKWebView, like so...

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
  }
}

...然后按如下所述使用它...

...and then using it as follows...


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中惯用的方式?

When the user taps the Button, I want to somehow call goBack on the WKWebView. How am I to do this idiomatically in SwiftUI?

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

Approaches I've considered that I think are either brittle or aren't idiomatic SwiftUI...

  • 表示用户在绑定中单击返回"的次数.让WebView监听该绑定,并在绑定增加时移回.

  • Represent the number of times that a user has clicked "Back" in a binding. Have WebView listen to that binding and move back when that increments.

具有BrowserView创建一个名为MutableWebViewAPI之类的对象,并在构造时将其传递给WebView. WebView侦听此对象,以便当BrowserView调用类似MutableWebViewAPI.goBack()的内容时,WebView会执行相同的操作.

Have BrowserView create an object called something like MutableWebViewAPI and pass it to WebView on construction. WebView listens on this object so that when BrowserView calls something like MutableWebViewAPI.goBack(), WebView does the same.

推荐答案

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

I think the best way is to leverage the power of Combine by creating a PassthroughSubject on your parent view and then subscribe to events in your child WebView.

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

First, create a struct in your UIViewReprsentable that captures the available events you want to send to your 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来创建这些事件.

Next, in your parent, create the PassthroughSubject to create these events.

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())
        }
    }
}

这篇关于在SwiftUI中控制嵌套UIView的惯用方式是什么的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆