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 WKWebView
di 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 body
dan sebutkan kerangka kerja yang digunakan untuk membungkus WKWebView.
EDIT 2 : Menambahkan kode untuk mengklarifikasi bahwa saya memerlukan komunikasi dua arah dari WKWebView
ke aplikasi asli melalui WKScriptMessageHandler
(untuk mendapatkan pemberitahuan ketika dokumen HTML siap) dan dari aplikasi asli ke WKWebView
melalui 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 lazy
variabel, 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)
}()