Cle*_*rem 27 javascript objective-c ios swift wkwebview
在WKWebView中,我们可以使用webkit消息处理程序调用ObjectiveC/swift代码,例如: webkit.messageHandlers.<handler>.pushMessage(message)
它适用于没有参数的简单javascript函数.但;
Cle*_*rem 11
不幸的是我找不到本机解决方案.
但以下解决方法解决了我的问题
使用javascript promises,您可以从iOS代码中调用resolve函数.
UPDATE
这就是你如何使用诺言
在JS中
this.id = 1;
this.handlers = {};
window.onMessageReceive = (handle, error, data) => {
if (error){
this.handlers[handle].resolve(data);
}else{
this.handlers[handle].reject(data);
}
delete this.handlers[handle];
};
}
sendMessage(data) {
return new Promise((resolve, reject) => {
const handle = 'm'+ this.id++;
this.handlers[handle] = { resolve, reject};
window.webkit.messageHandlers.<yourHandler>.postMessage({data: data, id: handle});
});
}
Run Code Online (Sandbox Code Playgroud)
在iOS中
window.onMessageReceive使用适当的处理程序ID 调用该函数
小智 9
有一种方法可以使用WkWebView从本机代码中将返回值返回给JS.这是一个小小的黑客,但没有问题我的工作正常,我们的生产应用程序使用了大量的JS/Native通信.
在分配给WKWebView的WKUiDelegate中,重写RunJavaScriptTextInputPanel.这使用委托处理JS提示函数来完成此任务的方式:
public override void RunJavaScriptTextInputPanel (WebKit.WKWebView webView, string prompt, string defaultText, WebKit.WKFrameInfo frame, Action<string> completionHandler)
{
// this is used to pass synchronous messages to the ui (instead of the script handler). This is because the script
// handler cannot return a value...
if (prompt.StartsWith ("type=", StringComparison.CurrentCultureIgnoreCase)) {
string result = ToUiSynch (prompt);
completionHandler.Invoke ((result == null) ? "" : result);
} else {
// actually run an input panel
base.RunJavaScriptTextInputPanel (webView, prompt, defaultText, frame, completionHandler);
//MobApp.DisplayAlert ("EXCEPTION", "Input panel not implemented.");
}
}
Run Code Online (Sandbox Code Playgroud)
在我的例子中,我传递数据类型= xyz,name = xyz,data = xyz来传递args.我的ToUiSynch()代码处理请求并始终返回一个字符串,它返回JS作为一个简单的返回值.
在JS中,我只是使用格式化的args字符串调用prompt()函数并获取返回值:
return prompt ("type=" + type + ";name=" + name + ";data=" + (typeof data === "object" ? JSON.stringify ( data ) : data ));
Run Code Online (Sandbox Code Playgroud)
这个答案使用了 Nathan Brown上面的答案的想法。
据我所知,目前没有办法将数据返回到 javascript同步方式。希望苹果在未来的版本中提供解决方案。
所以hack就是拦截来自js的提示调用。Apple 提供此功能是为了在 js 调用警报、提示等时显示本机弹出设计。现在因为提示是功能,您可以在其中向用户显示数据(我们将利用它作为方法 param )以及用户对此的响应提示将返回给 js(我们将利用它作为返回数据)
只能返回字符串。这是以同步方式发生的。
我们可以按如下方式实现上述想法:
在javascript 端: 通过以下方式调用 swift 方法:
function callNativeApp(){
console.log("callNativeApp called");
try {
//webkit.messageHandlers.callAppMethodOne.postMessage("Hello from JavaScript");
var type = "SJbridge";
var name = "functionOne";
var data = {name:"abc", role : "dev"}
var payload = {type: type, functionName: name, data: data};
var res = prompt(JSON.stringify (payload));
//{"type":"SJbridge","functionName":"functionOne","data":{"name":"abc","role":"dev"}}
//res is the response from swift method.
} catch(err) {
console.log('The native context does not exist yet');
}
}
Run Code Online (Sandbox Code Playgroud)
在swift/xcode 端执行如下操作:
实现协议WKUIDelegate,然后将实现分配给 WKWebviewsuiDelegate属性,如下所示:
self.webView.uiDelegate = self
Run Code Online (Sandbox Code Playgroud)现在写这个func webView来覆盖(?)/拦截prompt来自javascript的请求。
func webView(_ webView: WKWebView, runJavaScriptTextInputPanelWithPrompt prompt: String, defaultText: String?, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (String?) -> Void) {
if let dataFromString = prompt.data(using: .utf8, allowLossyConversion: false) {
let payload = JSON(data: dataFromString)
let type = payload["type"].string!
if (type == "SJbridge") {
let result = callSwiftMethod(prompt: payload)
completionHandler(result)
} else {
AppConstants.log("jsi_", "unhandled prompt")
completionHandler(defaultText)
}
}else {
AppConstants.log("jsi_", "unhandled prompt")
completionHandler(defaultText)
}}
Run Code Online (Sandbox Code Playgroud)如果你不调用completionHandler()then js 执行将不会继续。现在解析 json 并调用适当的 swift 方法。
func callSwiftMethod(prompt : JSON) -> String{
let functionName = prompt["functionName"].string!
let param = prompt["data"]
var returnValue = "returnvalue"
AppConstants.log("jsi_", "functionName: \(functionName) param: \(param)")
switch functionName {
case "functionOne":
returnValue = handleFunctionOne(param: param)
case "functionTwo":
returnValue = handleFunctionTwo(param: param)
default:
returnValue = "returnvalue";
}
return returnValue
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
26869 次 |
| 最近记录: |