コードをSwift 3.に更新する必要があります。以下のコードは完全に機能する元のソリューションですが、Xcode 8ベータ版とiOS 10ではSwift 3元のhtml + jsコードを使用してネイティブ側を呼び出すときに、userContentController
デリゲートが呼び出されません。
class ViewController: UIViewController, WKUIDelegate, WKScriptMessageHandler, WKNavigationDelegate,UIWebViewDelegate,CLLocationManagerDelegate,URLSessionDataDelegate,UIImagePickerControllerDelegate, UINavigationControllerDelegate {
....
func initWebView(){
// JAVASCRIPT PART
let contentController = WKUserContentController();
let jScript:String = "var meta = document.createElement('meta'); meta.setAttribute('name', 'viewport'); meta.setAttribute('content', 'width=device-width'); document.getElementsByTagName('head')[0].appendChild(meta);";
let wkUScript:WKUserScript = WKUserScript(source: jScript, injectionTime: WKUserScriptInjectionTime.atDocumentEnd, forMainFrameOnly: true);
contentController.addUserScript(wkUScript)
contentController.add(
self,
name: "refreshWebPage"
)
contentController.add(
self,
name: "forceStepBack"
)
contentController.add(
self,
name: "setPageTitle"
)
contentController.add(
self,
name: "allowBackNavigate"
)
contentController.add(
self,
name: "changeBackNavigationURL"
)
contentController.add(
self,
name: "changeLeftButtonIconVisibility"
)
contentController.add(
self,
name: "changeRightButtonIconVisibility"
)
contentController.add(
self,
name: "clearWebCache"
)
contentController.add(
self,
name: "changeMobileAndPassword"
)
let config = WKWebViewConfiguration()
config.userContentController = contentController
self.webView = WKWebView(frame: CGRect.zero, configuration: config)
self.view.translatesAutoresizingMaskIntoConstraints = false
self.webView!.navigationDelegate = self
self.webView!.uiDelegate = self;
self.webView!.scrollView.bounces = false;
view = webView
webView?.loadHTMLString(self.baseURL!, baseURL: nil)
}
...
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
print("JavaScript is sending a message: \(message.body)")
print("JavaScript is sending a message.name: \(message.name)")
}
私は多くの時間と条件をデバッグした後、それを見つけました:
JSの関数
postMessage()
にはparameterが必要ですparameterはnullにできませんパラメータは
JSON
タイプでなければなりません例:
webkit.messageHandlers.refreshWebPage.postMessage("status":"ok");
上記の3つのアドバイスに従ってデリゲートを正しく設定した場合。デリゲート関数didReceiveScriptMessage
が呼び出されます。これがお役に立てば幸いです。
私はこれを次のような1つのcontentControllerだけを持つことで修正しました
let contentController = WKUserContentController()
contentController.add(self, name: "MyStuff")
次に、userContentController関数で本体を解析して、要求されたアクションとその他のパラメーターを判別します。 {action: "doThis"、params:[1,2,3]}を送信すると、解析コードは次のようになります。
if message.name == "MyStuff" {
let cmd:NSDictionary = message.body as! NSDictionary
let action:String = cmd["action"] as! String
switch action {
case "doThis":
// Do my stuff
break
default:
break
}
}
あなたはそれを修正する方法を見つけましたか?私にも問題がありますが、幸いにもメッセージを送信でき、userContentControllerがコールバックしましたが、メッセージのみが数字のみで、文字列も文字もない必要があります。理由はわかりません...
編集済みこれに関する答えを見つけました。あなたはトライキャッチを入れなければならないようです、そして私がそれをした後それはテキスト番号またはjsonでさえ100%働いています
`<script>
function callNative(message) {
try {
webkit.messageHandlers.callbackHandler.postMessage(message)
} catch(err) {
console.log("Error")
}
}
</script>`
callbackHandler
を機能させるには、iOSで同じWordにする必要があることを忘れないでください。callbackHandlerに名前を付ける必要はありません。任意の名前を付けることができますが、両方のJavaScriptで同じにする必要があります。およびiOS
それがあなたを助けることを願っています
基本的にwindow.webkit.messageHandlers
はUserMessageHandlersNamespace
タイプです。
文字列や配列の代わりに辞書を渡そうとする必要があります:
JavaScriptの部分:
var dictionary = {"key1":"value1", "key2":"value2", "subDictionary": {"name": "foo"}}
webkit.messageHandlers.refreshWebPage.postMessage(dictionary);
スイフト部分:
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
let body = message.body
if let dict = body as? Dictionary<String, AnyObject> {
if let test = dict["key1"] {
print("JavaScript is sending a message \(value1)")
}
}
}
P.S。(私のテストによれば、これはiOS9、iOS10の両方で機能します)