Ошибка webkit окна postMessage iOS Swift
Я пытаюсь создать библиотеку, которая открывает веб-представление в классе, где цель открывается, но не отображается на экране. Я создал и пытаюсь выполнить javaScript, который создает postMessage, чтобы получить результат, например, в методе userContentController(), но я получаю ошибку при его выполнении. Кроме того, я использую webView.callAsyncJavaScript, потому что тогда я хочу выполнить некоторые асинхронные функции, которые webView.evaluateJavaScript не позволяет. Кое-кто знает, в чем может быть причина, которая может мне помочь. Спасибо.
Код:
import WebKit
class FingerprintJs : NSObject, WKScriptMessageHandler, WKNavigationDelegate{
public func tryFinger(){
getWebView()
}
public func userContentController(_ userContentController: WKUserContentController,
didReceive message: WKScriptMessage){
print("userContentController")
print(message.name)
}
private func getWebView(){
if let viewController = UIWindow.key?.rootViewController {
if Thread.isMainThread {
let webView = self.makeWebView(viewController: viewController as! ViewController)
webView.loadHTMLString(getHtml(), baseURL: nil)
if #available(iOS 14.0, *) {
print("bunea")
webView.callAsyncJavaScript(getJavaScript()!, arguments: [:], in: nil, in: .defaultClient, completionHandler:{(result) in
print("queeeeee")
print(result as Any)
})
} else {
print("Llegaste aca? porqueee ")
// Fallback on earlier versions
}
// webView.evaluateJavaScript(getJavaScript()!,completionHandler:{(result , error) in
// if error == nil {
// print("success")
// print(result as Any)
// }
// else {
// print("error in executing js ", error!)
// }
// })
} else {
print("Llegaste aca? ")
}
}else{
NSLog("The UIApplication keyWindow of the rootViewController must be loaded first", "")
}
}
private func makeWebView(viewController: ViewController) -> WKWebView {
let preferences = WKPreferences()
preferences.javaScriptEnabled = true
let config = WKWebViewConfiguration()
config.userContentController.add(self, name: "message5")
config.preferences = preferences
let webView = WKWebView(frame: .init(x: 1.0, y: 1.0, width: 0, height: 0),
configuration: config)
webView.translatesAutoresizingMaskIntoConstraints = false
viewController.view.addSubview(webView)
return webView
}
private func getJavaScript() -> String?{
var javaScript: String? = nil
if let jsSourcePath = Bundle.main.path(forResource: "ejemplo", ofType: "js") {
do {
javaScript = try String(contentsOfFile: jsSourcePath)
}
catch {
NSLog("getJavaScriptString: "+(error.localizedDescription), "")
}
}
return javaScript
}
private func getHtml() -> String {
let html: String =
"""
<html>
<body>
<script>
</script>
</body>
</html>
"""
return html
}
private var webView: WKWebView? {
didSet {
oldValue?.removeFromSuperview()
oldValue?.configuration.userContentController.removeScriptMessageHandler(forName: "message5")
}
}
}
extension UIWindow {
static var key: UIWindow? {
if #available(iOS 13, *) {
return UIApplication.shared.windows.first { $0.isKeyWindow }
} else {
return UIApplication.shared.keyWindow
}
}
}
Javascript :
testFunct();
function testFunct() {
window.webkit.messageHandlers.message5.postMessage("nice" )
}
Ошибка :
failure(Error Domain=WKErrorDomain Code=4 "A JavaScript exception occurred" UserInfo={WKJavaScriptExceptionLineNumber=0, WKJavaScriptExceptionMessage=TypeError: undefined is not an object (evaluating 'window.webkit.messageHandlers'), WKJavaScriptExceptionColumnNumber=0, NSLocalizedDescription=A JavaScript exception occurred})
Кроме того, например, здесь у меня есть некоторые изменения кода, но, например, я никогда не получаю в методе userContentController сообщение. Где я установил window.webkit.messageHandlers в html.
import WebKit
import UIKit
class FingerprintJs : NSObject, WKScriptMessageHandler, WKNavigationDelegate{
public func tryFinger(){
getWebView()
}
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
assert(message.name == "myMessageName")
}
private func getWebView(){
if let viewController = UIWindow.key?.rootViewController {
if Thread.isMainThread {
let webView = self.makeWebView(viewController: viewController as! ViewController)
webView.loadHTMLString(getHtml(), baseURL: nil)
// webView.evaluateJavaScript(getJavaScript()!,completionHandler:{(result , error) in
// if error == nil {
// print("success")
// print(result as Any)
// }
// else {
// print("error in executing js ", error!)
// }
// })
} else {
print("Llegaste aca? ")
}
}else{
NSLog("The UIApplication keyWindow of the rootViewController must be loaded first", "")
}
}
private func makeWebView(viewController: ViewController) -> WKWebView {
let preferences = WKPreferences()
preferences.javaScriptEnabled = true
let config = WKWebViewConfiguration()
config.userContentController.add(self, name: "myMessageName")
config.preferences = preferences
let webView = WKWebView(frame: .init(x: 1.0, y: 1.0, width: 0, height: 0),
configuration: config)
webView.translatesAutoresizingMaskIntoConstraints = false
viewController.view.addSubview(webView)
webView.navigationDelegate = self
return webView
}
private func getJavaScript() -> String?{
var javaScript: String? = nil
if let jsSourcePath = Bundle.main.path(forResource: "ejemplo", ofType: "js") {
do {
javaScript = try String(contentsOfFile: jsSourcePath)
}
catch {
NSLog("getJavaScriptString: "+(error.localizedDescription), "")
}
}
return javaScript
}
private func getHtml() -> String {
let html: String =
"""
<html>
<body>
<script>
window.webkit.messageHandlers.myMessageName.postMessage("message")
</script>
</body>
</html>
"""
return html
}
private var webView: WKWebView? {
didSet {
oldValue?.removeFromSuperview()
oldValue?.configuration.userContentController.removeScriptMessageHandler(forName: "message5")
}
}
}
extension UIWindow {
static var key: UIWindow? {
if #available(iOS 13, *) {
return UIApplication.shared.windows.first { $0.isKeyWindow }
} else {
return UIApplication.shared.keyWindow
}
}
}
1 ответ
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
webView.evaluateJavaScript("testFunct()")
}
попробуйте вызвать метод JS из метода навигации didFinish после загрузки веб-представления. Это может быть связано с вызовом метода JS до того, как веб-представление будет загружено должным образом.