gpt4 book ai didi

ios - SwiftUI 中的 WKWebView - 用户与网站交互时如何切换 View ?

转载 作者:行者123 更新时间:2023-12-04 21:51:03 25 4
gpt4 key购买 nike

我的情况如下:我有一个 SwiftUI 应用程序并且想要显示一个 WebView。当用户点击该 WebView 中的某个按钮时,我希望将用户重定向到下一个(SwiftUI) View 。
我使用 UIViewRepresentable,因为这似乎是在 SwiftUI 中显示 WebView 的当前方式,因为它是通往 UIKit 的桥梁。
问题是: UIViewRepresentable 没有 正文 .那么我在哪里告诉 View 切换呢?在通常的 SwiftUI View 中,我会有一个模型,我会更新它,然后对主体中的模型变化使用react。

我设置了一个示例,其中 https://www.google.com在 WebView 中呈现。当用户发送搜索查询时,会调用协调器,该协调器会调用 UIViewRepresentable 的函数:

查看 - 这是应该通过显示另一个 View (通过 NavigationLinks 实现)对模型更改使用react的 View

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 搜索”使用react并调用协调器
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()
}
}

更新

我现在有一个带有模型的 View ( @ObservedObject )。这个模型给 UIViewControllerRepresentable .当用户点击“谷歌搜索”时, UIViewControllerRepresentable 成功调用 model.startCamera() .但是,模型的这种变化并没有反射(reflect)在 中。 WebviewContainer .这是为什么?这不就是 的全部目的吗? @ObservedObject 年代?

最佳答案

我添加了 Model到提供的代码,当 startCamera() 更新时函数被调用。 @Published变量应该在 UI 线程上更新,因为在大多数情况下,它们会更改 UI 状态,从而导致 UI 更新。

这是完整的示例:

import SwiftUI
import Foundation
import WebKit

class Coordinator: NSObject {
var webview: Webview

init(_ webview: Webview) {
self.webview = webview
}

@objc func startCamera(sender: WKWebView) {
webview.startCamera()
}
}

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

class WebviewModel: ObservableObject {
@Published var loggedOut: Bool = false
@Published var shouldRedirectToCameraView: Bool = false
@Published var navbarHidden: Bool = false
func startCamera() {
print("Started Camera")
DispatchQueue.main.async {
self.shouldRedirectToCameraView.toggle()
}
}
}

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

struct LoginView: View {
var body: some View {
Text("Login")
}
}

struct CameraView: View {
@ObservedObject var model: WebviewModel
var body: some View {
Text("CameraView")
}
}

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("Hallo"))
.navigationBarHidden(self.model.navbarHidden)

NavigationLink(destination: CameraView(model: self.model), isActive: $model.shouldRedirectToCameraView) {
EmptyView()
}
.navigationBarTitle(Text(""))
.navigationBarHidden(self.model.navbarHidden)
Webview(model: self.model)
}
}
}
}


struct ContentView: View {

var body: some View {
WebviewContainer()
}
}

struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}


Demo

我希望这有帮助。

关于ios - SwiftUI 中的 WKWebView - 用户与网站交互时如何切换 View ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58929485/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com