SwiftUI 在 link 单击 WKWebView 内部打开一个新视图

SwiftUI open a new View on link click inside of WKWebView

我想在WKWebView里面点击一个link后在SwfitUI(webview)中打开一个新视图,我不知道该怎么做。我知道你必须通过协调员,但我不知道更多。我在 swift.

的水平不是很高

这是我的 Swiftui 视图(我删除了多余的元素)和 al calsse 以在我的视图中显示我的内容:

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 

        
        
              
        
        
        
    }
 }   

提前致谢。

我终于找到了解决问题的方法。您必须使用协调器来了解何时单击 link 并检索 link.

使用绑定,我将 url 传输到视图,然后打开一个 sheetView,在里面我有我的 webview,它打开了 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)
        }
    }
    
    
}



}