我设置了一个示例,在其中 https://www.google.com 在WebView中呈现。当用户发送搜索查询时,协调器被调用,该协调器调用UIViewRepresentable的函数: View - 这是应该通过显示另一个视图(使用NavigationLinks实现)来对模型更改做出反应的视图。
import SwiftUI
struct WebviewContainer: View {
@ObservedObject var model: WebviewModel = WebviewModel()
var body: some View {
return NavigationView {
VStack {
NavigationLink(destination: LoginView(), isActive: $model.loggedOut) {
EmptyView()
}.isDetailLink(false)
.navigationBarTitle(Text(""))
.navigationBarHidden(self.model.navbarHidden)
NavigationLink(destination: CameraView(model: self.model), isActive: $model.shouldRedirectToCameraView) {
EmptyView()
}
.navigationBarTitle(Text(""))
.navigationBarHidden(self.model.navbarHidden)
Webview(model: self.model)
}
}
}
}
UIViewControllerRepresentable - 这是在SwiftUI上下文中使用WKWebview所必需的。
import SwiftUI
import WebKit
struct Webview : UIViewControllerRepresentable {
@ObservedObject var model: WebviewModel
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeUIViewController(context: Context) -> EmbeddedWebviewController {
let webViewController = EmbeddedWebviewController(coordinator: context.coordinator)
webViewController.loadUrl(URL(string:"https://www.google.com")!)
return webViewController
}
func updateUIViewController(_ uiViewController: EmbeddedWebviewController, context: UIViewControllerRepresentableContext<Webview>) {
}
func startCamera() {
model.startCamera()
}
}
UIViewController 是 WKNavigationDelegate,它可以在用户点击“Google搜索”时响应并调用协调器。
import UIKit
import WebKit
class EmbeddedWebviewController: UIViewController, WKNavigationDelegate {
var webview: WKWebView
var router: WebviewRouter? = nil
public var delegate: Coordinator? = nil
init(coordinator: Coordinator) {
self.delegate = coordinator
self.webview = WKWebView()
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
self.webview = WKWebView()
super.init(coder: coder)
}
public func loadUrl(_ url: URL) {
webview.load(URLRequest(url: url))
}
override func loadView() {
self.webview.navigationDelegate = self
view = webview
}
func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) {
guard let url = (navigationResponse.response as! HTTPURLResponse).url else {
decisionHandler(.cancel)
return
}
if url.absoluteString.starts(with: "https://www.google.com/search?") {
decisionHandler(.cancel)
self.delegate?.startCamera(sender: self.webview)
}
else {
decisionHandler(.allow)
}
}
override func viewDidLoad() {
super.viewDidLoad()
}
}
协调人 - 在WKNavigationDelegate和UIViewRepresentable之间建立桥梁。
import Foundation
import WebKit
class Coordinator: NSObject {
var webview: Webview
init(_ webview: Webview) {
self.webview = webview
}
@objc func startCamera(sender: WKWebView) {
webview.startCamera()
}
}
更新
现在我有一个带模型的视图(@ObservedObject)。这个模型被给到了UIViewControllerRepresentable中。当用户点击“Google Search”时,UIViewControllerRepresentable成功调用了model.startCamera()。然而,这个模型的改变并没有反映在WebviewContainer中。为什么会这样?这不是@ObservedObject的全部目的吗?
@ObservedObject
或@EnvironmentObject
)传递到你的 Webview 中,并在doSomething
中更改一些@Published
属性,具体取决于你的 ContentView 显示的值(或导航到的值),以显示其他视图。 - Asperi