I would like to open a new view in SwfitUI (webview) after clicking on a link inside of WKWebView, I do not know how to do. I understand that you have to go through Coordinator, but I don't know more. I don't have a very high level in swift.
Here is my Swiftui view (I removed superfluous elements) and al calsse to display my content in my view :
struct PostDetailView: View {
var p: Post
@ObservedObject var dataManager: DataManager
let preferences:Preferences = parsePreferences()
let contentWebView = ArticleCustomView()
@State var showComments = false
@Binding var favorite: Bool
@Environment(\.colorScheme) var colorScheme
var body: some View {
let content: String = contentWebView.contentArticle(title: p.title.rendered.stringByDecodingHTMLEntities, content: p.content.rendered, date: formatDateDetailPost(dateToChange: p.date), author: p.author_meta.nickname)
ZStack{
BackgroundView()
articleWebView(text: content, color: colorScheme)
}
.navigationBarTitle(...)
.navigationBarItems(...)
}
}
x
struct articleWebView: UIViewRepresentable {
@State var text: String
@State var color: ColorScheme
func makeUIView(context: Context) -> WKWebView {
return _wkwebview
}
func updateUIView(_ uiView: WKWebView, context: Context) {
var html = ""
var normalizeCSS: String = ""
var articlesCSS: String = ""
//let articlesDarkCSS: String
let altCSS: String
altCSS = "-dark"
guard let fileURL = Bundle.main.url(forResource: "articles", withExtension: "html") else { return print("articles.html introuvable")}
guard let fileURLNormalizeCss = Bundle.main.url(forResource: "normalize", withExtension: "css") else { return print("normalize.css introuvable")}
guard let fileURLArticlesCss = Bundle.main.url(forResource: "articles\(altCSS)", withExtension: "css") else { return print("articles\(altCSS).css introuvable")}
do {
html = try String(contentsOf: fileURL)
} catch {
print("Unable to get the articles.html")
}
do {
normalizeCSS = try String(contentsOf: fileURLNormalizeCss)
} catch {
print("Unable to get the normalize.css")
}
do {
articlesCSS = try String(contentsOf: fileURLArticlesCss)
} catch {
print("Unable to get the articles.css")
}
html = html.replacingOccurrences(of: "[article:content]", with: text)
html = html.replacingOccurrences(of: "[normalize:CSS]", with: normalizeCSS)
html = html.replacingOccurrences(of: "[style:articles]", with: articlesCSS)
uiView.loadHTMLString(html, baseURL: nil)
//----------------------------------------------//
uiView.allowsBackForwardNavigationGestures = true
uiView.isOpaque = false
uiView.backgroundColor = .clear
uiView.scrollView.backgroundColor = UIColor.clear
uiView.scrollView.showsVerticalScrollIndicator = false
uiView.scrollView.pinchGestureRecognizer?.isEnabled = false
}
}
Thank you in advance.
CodePudding user response:
I finally found a solution to my problem. You have to use the Coordinator to know when there is a click on a link and to retrieve the link.
Using Binding I transfer the url to the view and I open a sheetView and inside I have my my webview which opens the url
struct PostDetailView: View {
var p: Post
@ObservedObject var dataManager: DataManager
let preferences:Preferences = parsePreferences()
let contentWebView = ArticleCustomView()
@State var showComments = false
@Binding var favorite: Bool
@State var activeSheet: Bool = false
@State var urlToOpenInSheet: String = ""
@Environment(\.colorScheme) var colorScheme
var body: some View {
let content: String = contentWebView.contentArticle(title: p.title.rendered.stringByDecodingHTMLEntities, content: p.content.rendered, date: formatDateDetailPost(dateToChange: p.date), author: p.author_meta.nickname)
ZStack{
BackgroundView()
articleWebView(text: content, color: colorScheme, activeSheet: $activeSheet, urlToOpenInSheet: $urlToOpenInSheet)
}
.navigationBarTitle(...)
.navigationBarItems(...)
.sheet(isPresented: $activeSheet) {
if !urlToOpenInSheet.isEmpty {
ExternalWebView(urlToVisite: urlToOpenInSheet, activeButtons: true, fromSheet: true, closeSheet: $activeSheet)
.ignoresSafeArea()
.accentColor(.white)
}
}
.onChange(of: urlToOpenInSheet) { newValue in
print("url changed to \(urlToOpenInSheet)!")
}
}
}
struct articleWebView: UIViewRepresentable {
@State var text: String
@State var color: ColorScheme
@Binding var activeSheet: Bool
@Binding var urlToOpenInSheet: String
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeUIView(context: Context) -> WKWebView {
let WKWebView = WKWebView()
WKWebView.navigationDelegate = context.coordinator
return WKWebView
}
func updateUIView(_ uiView: WKWebView, context: Context) {
var html = ""
var normalizeCSS: String = ""
var articlesCSS: String = ""
//let articlesDarkCSS: String
let altCSS: String
guard let fileURL = Bundle.main.url(forResource: "articles", withExtension: "html") else { return print("articles.html introuvable")}
guard let fileURLNormalizeCss = Bundle.main.url(forResource: "normalize", withExtension: "css") else { return print("normalize.css introuvable")}
guard let fileURLArticlesCss = Bundle.main.url(forResource: "articles\(altCSS)", withExtension: "css") else { return print("articles\(altCSS).css introuvable")}
do {
html = try String(contentsOf: fileURL)
} catch {
print("Unable to get the articles.html")
}
do {
normalizeCSS = try String(contentsOf: fileURLNormalizeCss)
} catch {
print("Unable to get the normalize.css")
}
do {
articlesCSS = try String(contentsOf: fileURLArticlesCss)
} catch {
print("Unable to get the articles.css")
}
html = html.replacingOccurrences(of: "[article:content]", with: text)
html = html.replacingOccurrences(of: "[normalize:CSS]", with: normalizeCSS)
html = html.replacingOccurrences(of: "[style:articles]", with: articlesCSS)
//print(html)
uiView.loadHTMLString(html, baseURL: nil)
//---------------------- Activer /Desactiver certaines options sur la Webview -------------------------//
uiView.allowsBackForwardNavigationGestures = true
uiView.isOpaque = false
uiView.backgroundColor = .clear
uiView.scrollView.backgroundColor = UIColor.clear
uiView.scrollView.showsVerticalScrollIndicator = false // indicateur de scroll
uiView.scrollView.pinchGestureRecognizer?.isEnabled = false // zommer-dezommer avec le doigt
}
class Coordinator: NSObject, WKNavigationDelegate, WKUIDelegate {
var parent: articleWebView
init(_ parent: articleWebView) {
self.parent = parent
}
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
if navigationAction.navigationType == .linkActivated {
if let url = navigationAction.request.url {
if UIApplication.shared.canOpenURL(url) {
//UIApplication.shared.open(url)
print(url)
parent.urlToOpenInSheet = url.absoluteString
print(self.parent.urlToOpenInSheet)
parent.activeSheet = true
decisionHandler(.cancel)
} else {
decisionHandler(.allow)
}
}
} else {
//print("not a user click")
decisionHandler(.allow)
}
}
}
}