前言
在常见的hybridApp框架开发过程中,一般oc调用js时都是使用执行一段js调用到某个方法的方式,如下两种:
//UIWebView
- (nullable NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script;
//WKWebView
- (void)evaluateJavaScript:(NSString *)javaScriptString completionHandler:(void (^ _Nullable)(_Nullable id, NSError * _Nullable error))completionHandler;
通过这两种方式我们可以执行一段js,在交互过程中可以理解为调用一段预先定义好的callback函数去实现到js的回调。
同步返回值
开门见山话不多说,这里教大家如何简单实现同步返回,demo我甚至都不想给大家写了,因为实在是太简单了,并且不限于UIWebView或WKWebView,基本没有什么迁移的羁绊。
在UIWebView和WKWebView中有如下两个代理
//UIWebView 虽说是私有的,但是从来没有因此被拒过
- (NSString *)webView:(UIWebView *)sender runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText;
//WKUIDelegate
- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * _Nullable result))completionHandler;
下面看一下简单的调用过程
- 先来看WKWebview的情况
//js
var result = prompt("123");//直接返回
alert('return'+result);//'return123'
//oc
- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * _Nullable result))completionHandler{
//通过completionHandler将返回值传回js,在js层面实现直接返回的效果
completionHandler(prompt);
}
- 再来看UIWebview的情况
//js
var result = prompt("123");//直接返回
alert('return'+result);
//oc
//在UIWebview中得先子类化UIWebview并重写实现prompt的方法,之后便可直接使用
- (NSString *)webView:(UIWebView *)sender runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)text initiatedByFrame:(CGRect)frame{
//直接ruturn,在js层面实现直接返回的效果
return prompt;
}
可以看到,跨两种webvie的实现都可以使用同样的js代码(当然,即使用window.webkit.messageHandlers.currentCookies.postMessage也可以在js层面进行封装从来实现js api的一致性)去与oc交互,并能直接用变量接受到返回值,大大提高了代码可读性,让你不再陷与callback地狱之中!
最后还是附上demo吧:https://github.com/ycace/iOS-WebView-Sync-Return