我正试图将这个问题的答案抛在脑后:
What's the idiomatic way to control a nested UIView in SwiftUI
并从子(WebView
)发布事件并订阅ParentView
。
我可以在WebView
的构造函数中传递eventSender,例如:
WebView(eventSender: eventSender)
然后WebView
应该可以发送事件,但是如何订阅ParentView
中的已发布事件?
有人有一个优雅的解决方案吗?
通常我会使用@EnvironmentObject
,但这些似乎不能与UIViewRepresentable
一起使用。
更新-我在这里创建了要点:https://gist.github.com/mattlaver/45519a58de65a304b10acaee663b06a2
请注意,我的childView是一个类,而不是一个结构,因为它需要从NSObject继承才能使用navigationDelegate。
我想关闭此视图(导航导航插入时导航回到显示之前的状态)。
答案 0 :(得分:1)
如果您希望从UiViewRepresentable传递状态,则绑定是一种方法,但是您需要从协调器进行设置。例如:
struct WebView: UIViewRepresentable {
@Binding var state: Int // this can be whatever type
func makeUIView(context: UIViewRepresentableContext<WebView>) -> WKWebView {
let uiView = WKWebView()
uiView.navigationDelegate = context.coordinator
self.state = 0
return uiView
}
func updateUIView(_ uiView: WKWebView, context: UIViewRepresentableContext<WebView>) {
}
func makeCoordinator() -> WebView.Coordinator {
Coordinator(view: self)
}
class Coordinator: NSObject, WKNavigationDelegate {
let view: WebView
init(view: WebView) {
self.view = view
}
func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) {
self.view.state = 1 // the binding will update the parent
decisionHandler(.allow)
}
}
}
答案 1 :(得分:0)
您可以构建自己的Binding
并传递@EnvironmentObject
或@ObservedObject
所需的任何对象。
看起来@FetchRequest
在UIViewRepresentable
内运作良好(如果您使用的是CoreData
)
struct ContentView: View {
@EnvironmentObject var store: Store<AppState, AppAction>
var body: some View {
WebViewRepresentable(state: Binding<AppState>(get: { self.store.state }, set { _ in}))
}
}
struct WebViewRepresentable: UIViewRepresentable {
@Binding var state: AppState
[...]
}
来源:https://gist.github.com/svanimpe/152e6539cd371a9ae0cfee42b374d7c4
答案 2 :(得分:0)
我在这里回答了这个问题:How to access content view's elements later in SwiftUI?
(我也是您引用的帖子中另一个被接受的答案)
您基本上想设置一个传入的处理程序,SwiftUI经常使用这种方法(请参阅TextField
在各种事件上的传入的处理程序选项。)
struct WebViewRepresentable: UIViewRepresentable {
let onEvent: (AppState) -> Void
// not sure what events you're talking about, probably `WKWebView` specific so tailor this to those needs
fun eventReceived(event: AppState) {
self.onEvent(event)
}
然后在您的父视图中:
var body: some View {
WebViewRepresentable { event in
// handle your event
}
}