Inicializar o membro na estrutura da vista
Eu quero ter um WKWebView com manipulação de JavaScript no SwiftUI. Na inicialização de variáveis Swift , estou fazendo o seguinte: (estou usandohttps://github.com/kylehickinson/SwiftUI-WebViewpara fornecer um wrapper para WKWebView
SwiftUI que também adiciona restrições de layout valiosas.)
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)
}()
}
Mas então eu aprendi com o membro da instância não pode ser usado no tipo que isso não funciona porque o fechamento não tem referência a si mesmo. Preciso que o WKWebView tenha um objeto de configuração dedicado, portanto, não posso simplesmente usar o outro construtor. Eu preciso de uma referência para fazer evaluateJavaScript
.
Como fazer isso funcionar?
EDIT 1 : Adicione o body
e mencione a estrutura usada para envolver WKWebView.
EDIT 2 : código adicionado para esclarecer que preciso de comunicações bidirecionais do WKWebView
aplicativo nativo via WKScriptMessageHandler
(para ser notificado quando o documento HTML estiver pronto) e do aplicativo nativo para WKWebView
via evaluateJavaScript
(para transferir dados quando o documento HTML estiver pronto).
Respostas
Uma solução possível é configurar WKWebView em 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()
}
Apenas torne myWebView uma lazy
variável, isso garante que o jsHandler seja inicializado antes do 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)
}()