从 child 发布消息到 parent 查看
Publish a message from child to parent View
我正试图翻转这个问题的答案:
并发布来自 child (WebView
) 的事件并订阅 ParentView
。
我可以在 WebView
的构造函数中传递 eventSender,例如:
WebView(eventSender: eventSender)
那么 WebView
应该可以发送事件,但是如何订阅 ParentView
中发布的事件?
谁有优雅的解决方案?
通常我会使用 @EnvironmentObject
但这些似乎不适用于 UIViewRepresentable
。
更新 - 我在这里创建了一个问题的要点:https://gist.github.com/mattlaver/45519a58de65a304b10acaee663b06a2
请注意,我的 childView 是 class,而不是结构,因为它需要从 NSObject 继承才能使用 navigationDelegate。
我想关闭此视图(在 navigationDelegate 启动时导航回到它显示之前)。
您可以构建自己的 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
我在这里回答了这个问题:
(我也是您所引用 post 的另一个已接受答案)
您基本上想要设置一个传入的处理程序,这是 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
}
}
如果您希望从 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)
}
}
}
我正试图翻转这个问题的答案:
并发布来自 child (WebView
) 的事件并订阅 ParentView
。
我可以在 WebView
的构造函数中传递 eventSender,例如:
WebView(eventSender: eventSender)
那么 WebView
应该可以发送事件,但是如何订阅 ParentView
中发布的事件?
谁有优雅的解决方案?
通常我会使用 @EnvironmentObject
但这些似乎不适用于 UIViewRepresentable
。
更新 - 我在这里创建了一个问题的要点:https://gist.github.com/mattlaver/45519a58de65a304b10acaee663b06a2
请注意,我的 childView 是 class,而不是结构,因为它需要从 NSObject 继承才能使用 navigationDelegate。
我想关闭此视图(在 navigationDelegate 启动时导航回到它显示之前)。
您可以构建自己的 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
我在这里回答了这个问题:
(我也是您所引用 post 的另一个已接受答案)
您基本上想要设置一个传入的处理程序,这是 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
}
}
如果您希望从 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)
}
}
}