如何在 SwiftUI ScrollView 中显示 MathJax 字符串?

问题描述

我收到来自 MathJax 响应的 String API,需要在 WKWebView 中的 SwiftUI显示。这是一个示例 String

"<img alt=\"\" height=\"2305\" src=\"https:\/\/s3-us-west-2.amazonaws.com\/infinitestudent-images\/ckeditor_assets\/pictures\/37732\/content_types_of_combustion.jpg\" width=\"800\" \/>"

这是我试过的代码

import SwiftUI
import WebKit

struct Model: Codable {
    var mathjaxBody: String?
    var answer: Answer
}

struct MathJaxView: View {

    let model: Model

    var body: some View {
        ScrollView {
            AnswerSectionView(answer: model.answer)
            HTMLView(htmlString: model.mathjaxBody)
                .frame(minWidth: 100,maxWidth: .infinity,minHeight: 100,maxHeight: .infinity)
        }
    }
}

struct HTMLView: UIViewRepresentable {
    var htmlString: String?

    func makeUIView(context: Context) -> WKWebView {
        WKWebView(frame: .zero)
    }

    func updateUIView(_ uiView: WKWebView,context: Context) {
        guard let string = htmlString else { return }
        uiView.loadHTMLString(string,baseURL: nil)
    }
}

它需要在一个 ScrollView 中,上面有一些不同的细节,在 ScrollView 中正确显示。但是,HTMLView 没有出现。我尝试添加 .frame(minWidth: 100,maxHeight: .infinity) 但仍然没有显示

解决方法

解决方案是简单地通过 evaluateJavaScript("document.body.scrollHeight") 方法计算所需的高度,然后使用其他一些方法将其应用到 WebView 组件。

struct WebView: UIViewRepresentable {

    var htmlString: String?

    @EnvironmentObject var viewModel: WebViewModel

    func makeUIView(context: Context) -> WKWebView {
        let webView = WKWebView(frame: .zero)
        webView.backgroundColor = .clear
        webView.navigationDelegate = context.coordinator
        webView.scrollView.isScrollEnabled = false
        return webView
    }

    func updateUIView(_ uiView: WKWebView,context: Context) {
        guard let string = htmlString else { return }
        uiView.loadHTMLString(string,baseURL: nil)
    }

    class Coordinator: NSObject,WKNavigationDelegate {

        private var viewModel: WebViewModel

        init(viewModel: WebViewModel) {
            self.viewModel = viewModel
        }

        func webView(_ webView: WKWebView,didFinish navigation: WKNavigation!) {
            webView.evaluateJavaScript("document.readyState") { (complete,error) in
                if complete != nil {
                    webView.evaluateJavaScript("document.body.scrollHeight") { (height,error) in
                        if let height = height as? CGFloat,self.viewModel.contentHeight == 0 {
                            self.viewModel.contentHeight = height * 0.4
                        }
                    }
                }
            }
        }
    }

    func makeCoordinator() -> Coordinator {
        Coordinator(viewModel: viewModel)
    }
}

class WebViewModel: ObservableObject {
    @Published var contentHeight: CGFloat = 0
}

struct MathJaxView: View {

    let model: Model

    var body: some View {
        ScrollView {
            AnswerSectionView(answer: model.answer)
            WebView(htmlString: model.mathjaxBody)
                .environmentObject(webViewModel)
                .frame(height: webViewModel.contentHeight)
                .frame(maxWidth: .infinity)
                .fixedSize(horizontal: false,vertical: true)
        }
    }
}