plan
- WKWebView – Intercepts urls
- WKWebView – MessageHandler
MessageHandler scheme is more elegant, but considering the compatibility with Android, we adopt WKWebView-intercepting URL scheme.
Usage scenarios/requirements
After clicking the button on the H5 page of scene A, the App only needs to complete the operation.
After the button is clicked on the H5 page of scene B, the App will notify H5 of the operation result when it needs to operate.
Scenario A and SCENARIO B both involve communication between H5 and App, but scenario B has A callback operation. A callback is basically an App calling a JS function
App H5 communication basics
App notify JS
var js = "App.callJS()"
webView.evaluateJavaScript(js) { (response, error) in
}
Copy the code
JS notify App
var iframe = document.createElement("IFRAME");
iframe.setAttribute("src"."");
document.documentElement.appendChild(iframe);
iframe.parentNode.removeChild(iframe);
Copy the code
imagine
H5 sends the command to take a picture, and the App receives it and takes the picture. After taking the picture, it sends the picture to H5. So this is how we use the H5 page
// This parameter can be left blank
App.takePicture("Parameters".function(data) {
// Success, display the image
}, function(data) {
// Failed, error message
});
Copy the code
Train of thought
H5 identifies the uniqueness of an instruction with an ID, which is associated with the name, parameter, and callback of the current instruction. The App uses the ID to get the name, the parameter, and the callback.
Get the callback function by ID and use setTimeout to complete the JS function call.
// Execute the function with the same effect
setTimeout("App.callJS()".0);
App.callJS()
Copy the code
implementation
H5 core code
var AppServer = {
ID_COUNTER: 0.COMMAND_NAME_SET: {},
COMMAND_ARGS_SET: {},
COMMAND_SUCCESS_COMPLETION_SET: {},
COMMAND_FAIL_COMPLETION_SET: {},
// JS calls App
callNative: function (cmd_name, cmd_args, cmd_success, cmd_fail) {
var key = this.ID_COUNTER++; // The unique identifier of the directive
this.COMMAND_NAME_SET[key] = cmd_name;
this.COMMAND_ARGS_SET[key] = cmd_args;
if (typeofcmd_success ! ='undefined') this.COMMAND_SUCCESS_COMPLETION_SET[key] = cmd_success;
if (typeofcmd_fail ! ='undefined') this.COMMAND_FAIL_COMPLETION_SET[key] = cmd_fail;
var iframe = document.createElement("IFRAME");
iframe.setAttribute("src"."DEMO://AppServer? id=" + key);
document.documentElement.appendChild(iframe);
iframe.parentNode.removeChild(iframe);
iframe = null;
},
// Directive name
getCommandName: function(key) {
return this.COMMAND_NAME_SET[key];
},
// Command parameters
getCommandArgs: function(key) {
return this.COMMAND_ARGS_SET[key];
},
// App calls JS
callJS: function (key, args) {
if (typeof args == "undefined") {
args = JSON.stringify({});
args = JSON.parse(args);
}
var data = args.data;
try {
data = JSON.stringify(data);
} catch(e) {
alert(e.message);
}
/ / callback
var status = args.status;
if (status == 1) {
/ / success
if (typeof this.COMMAND_SUCCESS_COMPLETION_SET[key] == "undefined") return;
setTimeout("AppServer.COMMAND_SUCCESS_COMPLETION_SET['" + key + "'] ('" + data + "')".0);
}
else if (status == 0) {
/ / fail
if (typeof this.COMMAND_FAIL_COMPLETION_SET[key] == "undefined") return;
setTimeout("AppServer.COMMAND_FAIL_COMPLETION_SET['" + key + "'] ('" + data + "')".0); }}};Copy the code
App core code
// Directive name
func getCommandName(_ commandID: String) {
let JS = "AppServer.getCommandName(\"\(commandID)\")"
webView.evaluateJavaScript(JS) { (response, error) in}}// Command parameters
func getCommandArguments(_ commandID: String) {
let JS = "AppServer.getCommandArgs(\"\(commandID)\")"
webView.evaluateJavaScript(JS) { (response, error) in}}// App calls JS
func callJS(_ commandID: String.data: String) {
let JS = "AppServer.callJS(\"\(commandID)\"," + data + ")"
webView.evaluateJavaScript(JS) { (response, error) in}}Copy the code
Implementation effect
Demo
Demo use
Feel good, star once 🌟
The H5 used by App is packaged and compiled, and the H5 project is under the my-project directory. For actual project use, H5 only needs to introduce appServer. js file and agree instruction name and parameters with App.
supplement
If you want to test custom instructions, you can modify the H5 project yourself. H5 Demo using Vue to write, modify directly compiled package. After Xcode has been cleaned (Shift + Command + k), rerunning will see the changes.