반응형
Feature
- SwfitUI에서 HTML을 출력한다.
- HTML - 링크 클릭 시, 활성화된 링크를 가져오거나, 핸들러를 제공한다.
- HTML에 CSS를 적용한다.
import SwiftUI
import WebKit
///참고 - https://stackoverflow.com/a/59018581/3374327
struct SUIWebView: UIViewRepresentable {
@ObservedObject var viewModel: SUIWebViewModel
let url: URL?
let html: String?
let css: String?
func makeUIView(context: UIViewRepresentableContext<SUIWebView>) -> WKWebView {
var webView: WKWebView!
if let url = url {
let request = URLRequest(url: url, cachePolicy: .returnCacheDataElseLoad)
webView = .init()
webView.load(request)
} else if let html = html {
if let css = css {
let source = """
var style = document.createElement('style');
style.innerHTML = '\(css)';
document.head.appendChild(style);
"""
let userScript = WKUserScript(source: source,
injectionTime: .atDocumentEnd,
forMainFrameOnly: true)
let userContentController = WKUserContentController()
userContentController.addUserScript(userScript)
let configuration = WKWebViewConfiguration()
configuration.userContentController = userContentController
webView = .init(frame: .zero, configuration: configuration)
} else {
webView = .init()
}
webView.loadHTMLString(html, baseURL: nil)
}
webView.navigationDelegate = context.coordinator
return webView
}
func updateUIView(_ webview: WKWebView, context: UIViewRepresentableContext<SUIWebView>) {
}
final class Coordinator: NSObject, WKNavigationDelegate {
private var viewModel: SUIWebViewModel
init(_ viewModel: SUIWebViewModel) {
self.viewModel = viewModel
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
//print("WebView: navigation finished")
self.viewModel.didFinishLoading = true
}
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
if navigationAction.navigationType == WKNavigationType.linkActivated {
if let url = navigationAction.request.mainDocumentURL {
self.viewModel.activedLinkURL = url
self.viewModel.navigateFunc?(url)
}
decisionHandler(.cancel)
return
}
decisionHandler(.allow)
}
}
func makeCoordinator() -> SUIWebView.Coordinator {
Coordinator(viewModel)
}
}
final class SUIWebViewModel: ObservableObject {
@Published var activedLinkURL: URL?
@Published var didFinishLoading: Bool = false
var navigateFunc: ((URL) -> Void)?
}
private let css = "body { font-size: 2.4rem; font-weight: normal; font-stretch: normal; line-height: 1.21; letter-spacing: 0;text-align: left; color: #666666; }"
VStack {
SUIWebView(viewModel: webViewModel, url: nil, html: term.termsDetailContents, css: css)
if webViewModel.didFinishLoading {
let _ = logD("didFinishLoading")
}
}
반응형
'Develop > Swift' 카테고리의 다른 글
String에 HTML 링크 적용 (0) | 2023.01.07 |
---|---|
KingFisher에서 SVG 이미지 다운로드하는 방법 (0) | 2022.11.13 |
multi-line 문구 localizable.strings 적용 방법 (0) | 2022.10.13 |
UserDefaults 모든 항목 출력, 경로, 리셋 (0) | 2022.09.06 |
Advances in Collection View Layout (0) | 2022.09.04 |