Inisialisasi anggota dalam tampilan struct
Saya ingin memiliki WKWebView dengan penanganan JavaScript di SwiftUI. Dari Inisialisasi Variabel Swift , saya melakukan hal berikut: (Saya menggunakanhttps://github.com/kylehickinson/SwiftUI-WebViewuntuk menyediakan pembungkus WKWebViewdi SwiftUI yang juga menambahkan batasan tata letak yang berharga.)
struct ContentView: View {
var body: some View {
WebView(webView: myWebView)
.onAppear {
let url = Bundle.main.url(forResource: "index", withExtension: "html")!
myWebView.loadFileURL(url, allowingReadAccessTo: url)
let request = URLRequest(url: url)
myWebView.load(request)
}
}
class JSHandler : NSObject, WKScriptMessageHandler {
var contentView: ContentView?
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
print("documentReady")
contentView!.myWebView.evaluateJavaScript("<Long Script to Transfer Data>") { (result, error) in
}
}
}
let myJSHandler = JSHandler()
var myWebView: WKWebView = {
let config = WKWebViewConfiguration()
let controller = WKUserContentController()
controller.add(myJSHandler , name: "documentReady")
config.userContentController = controller
return WKWebView(frame: .zero, configuration: config)
}()
}
Tapi kemudian saya belajar dari anggota Instance tidak dapat digunakan pada tipe yang ini tidak berfungsi karena closure tidak mengacu pada diri sendiri. Saya memerlukan WKWebView untuk mendedikasikan objek konfigurasi sehingga saya tidak bisa hanya menggunakan konstruktor lain. Saya perlu referensi untuk melakukannya evaluateJavaScript.
Bagaimana cara membuatnya bekerja?
EDIT 1 : Tambahkan bodydan sebutkan kerangka kerja yang digunakan untuk membungkus WKWebView.
EDIT 2 : Menambahkan kode untuk mengklarifikasi bahwa saya memerlukan komunikasi dua arah dari WKWebViewke aplikasi asli melalui WKScriptMessageHandler(untuk mendapatkan pemberitahuan ketika dokumen HTML siap) dan dari aplikasi asli ke WKWebViewmelalui evaluateJavaScript(untuk mentransfer data setelah dokumen HTML siap).
Jawaban
Salah satu solusi yang mungkin adalah mengonfigurasi WKWebView di init
struct ContentView: View {
private var myWebView: WKWebView
init() {
let config = WKWebViewConfiguration()
let controller = WKUserContentController()
controller.add(myJSHandler , name: "documentReady")
config.userContentController = controller
myWebView = WKWebView(frame: .zero, configuration: config)
}
var body: some View {
WebView(webView: myWebView)
.onAppear {
let url = Bundle.main.url(forResource: "index", withExtension: "html")!
myWebView.loadFileURL(url, allowingReadAccessTo: url)
let request = URLRequest(url: url)
myWebView.load(request)
}
}
class JSHandler : NSObject, WKScriptMessageHandler {
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
print("documentReady")
message.webView?.evaluateJavaScript("<Long Script to Transfer Data>") { (result, error) in
}
}
}
let myJSHandler = JSHandler()
}
Buat saja myWebView sebagai lazyvariabel, Ini memastikan bahwa jsHandler diinisialisasi sebelum WebView.
lazy var myWebView: WKWebView = {
let config = WKWebViewConfiguration()
let controller = WKUserContentController()
controller.add(myJSHandler , name: "documentReady")
config.userContentController = controller
return WKWebView(frame: .zero, configuration: config)
}()