Je suis un Swift apprenant. Je travaille avec Swiftui, qui est une structure, je dois mettre en œuvre une WKWebView et, dans cela, une URL change de manière dynamique. Je dois attraper ces URL changeantes, mais Des solutions que j'ai essayées ne fonctionnent pas.
Par exemple: https://stackoverflow.com/a/48273950/1008824 J'ai essayé ce bloc de code mais cela ne fonctionne pas et cela me donne des erreurs de compilation:
import SwiftUI
import WebKit
struct ContentView: UIViewRepresentable, WKNavigationDelegate {
let request = URLRequest(url: URL(string: "https://Apple.com")!)
func makeUIView(context: Context) -> WKWebView {
let preferences = WKPreferences()
preferences.javaScriptEnabled = true
preferences.javaScriptCanOpenWindowsAutomatically = true
let configuration = WKWebViewConfiguration()
configuration.preferences = preferences
let webView = WKWebView(frame: .zero, configuration: configuration)
webView.allowsBackForwardNavigationGestures = true
return webView
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
// 'override' can only be specified on class membe
if keyPath == #keyPath(WKWebView.url) {
print("### URL:", self.webView.url!)
}
if keyPath == #keyPath(WKWebView.estimatedProgress) {
// When page load finishes. Should work on each page reload.
if (self.webView.estimatedProgress == 1) {
print("### EP:", self.webView.estimatedProgress)
}
}
}
func updateUIView(_ uiView: WKWebView, context: Context) {
uiView.load(request)
}
func webViewDidFinishLoad(webView : WKWebView) {
print("Loaded: \(String(describing: webView.url))")
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
print("Loaded: \(String(describing: webView.url))")
//progressView.isHidden = true
}
func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
//progressView.isHidden = false
print("Loaded: \(String(describing: webView.url))")
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
J'ai un type de classement 'contentview' ne peut pas être conforme au protocole de classe "NSOBJUSTPROTOCOL" ERREUR AT LINE SHORT CONTENUVIEW ...
J'ai trouvé une très bonne solution à ma question. Je vais le poster ici. Peut-être que quelqu'un veut le voir et pourrait leur être utile.
observe.observation = uiView.observe(\WKWebView.url, options: .new) { view, change in
if let url = view.url {
// do something with your url
}
}
Vous pouvez simplement créer une classe de modèle ObservableObject de WebView avec le nom "WebviewModel" comme
class WebViewModel: ObservableObject {
@Published var link: String
@Published var didFinishLoading: Bool = false
init (link: String) {
self.link = link
}
}
et aussi importer
import WebKit
import Combine
puis copiez ces extraits de code
struct SwiftUIWebView: UIViewRepresentable {
@ObservedObject var viewModel: WebViewModel
let webView = WKWebView()
func makeUIView(context: UIViewRepresentableContext<SwiftUIWebView>) -> WKWebView {
self.webView.navigationDelegate = context.coordinator
if let url = URL(string: viewModel.link) {
self.webView.load(URLRequest(url: url))
}
return self.webView
}
func updateUIView(_ uiView: WKWebView, context: UIViewRepresentableContext<SwiftUIWebView>) {
return
}
class Coordinator: NSObject, WKNavigationDelegate {
private var viewModel: WebViewModel
init(_ viewModel: WebViewModel) {
self.viewModel = viewModel
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
//print("WebView: navigation finished")
self.viewModel.didFinishLoading = true
}
}
func makeCoordinator() -> SwiftUIWebView.Coordinator {
Coordinator(viewModel)
}
}
struct SwiftUIWebView_Previews: PreviewProvider {
static var previews: some View {
SwiftUIWebView(viewModel: WebViewModel(link: "https://google.com"))
//WebView(request: URLRequest(url: URL(string: "https://www.Apple.com")!))
}
}
et en vous voir
struct AnyView: View {
@ObservedObject var model = WebViewModel(link: "https://www.wikipedia.org/")
var body: some View {
NavigationView {
SwiftUIWebView(viewModel: model)
if model.didFinishLoading {
//do your stuff
}
}
}
}
donc, de cette façon, vous pouvez obtenir la réponse des déléguements des autres.
Vous pouvez utiliser l'observation de la clé/de la valeur pour détecter les modifications apportées à la propriété URL de WKWebView.
Voici un exemple simple d'emballage d'une WKWEBVIEW dans un UIViewrevisceptable.
Notez que parce que nous modifions une propriété, l'UIViewrePresentable est un final class
plutôt qu'une structure.
import Combine
import SwiftUI
import WebKit
final class WebView: UIViewRepresentable {
@Published var url: URL? = nil {
didSet {
if url != nil {
willChange.send(url)
}
}
}
private let view = WKWebView()
private var urlChangedObservation: NSKeyValueObservation?
private let willChange = PassthroughSubject<URL?, Never>()
func makeUIView(context: Context) -> WKWebView {
return makeWebView()
}
func updateUIView(_ uiView: WKWebView, context: Context) {
}
func display(_ html: String) {
self.view.loadHTMLString(html, baseURL: nil)
}
public func load(_ url: String) -> WebView {
let link = URL(string: url)!
let request = URLRequest(url: link)
self.view.load(request)
return self
}
func makeWebView() -> WKWebView {
self.urlChangedObservation = self.view.observe(\WKWebView.url, options: .new) { view, change in
if let url = view.url {
self.url = url
}
}
return self.view
}
}
Vous pouvez ensuite écouter la notification modifiée par l'URL dans l'ONRECEIVE () du conteneur Holding the webview:
.onReceive(self.webview.$url) { url in
if let url = url {
}
}