##UIWebViewjavascript
Native调用JS,使用
stringByEvaluatingJavaScriptFromString
来解释执行js脚本。html
//script即为要执行的js方法名称 - (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script;
**PS:**苹果推荐iOS8以后的app使用WKWebView
来代替UIWebView,同时也使用方法 evaluateJavaScript:completionHandler:
来替代stringByEvaluatingJavaScriptFromString,由于会一直等待stringByEvaluatingJavaScriptFromString方法执行完毕java
JS调用Native,须要经过UIWebView
拦截跳转请求并判断请求头
是不是协商好的协议头来判断是不是JS发起调用Native的请求。ios
<!-- more -->git
- webView:shouldStartLoadWithRequest:navigationType:
github
function callNative{ var url = ”callNative://nslogHelloWord“ window.location.href = url; }
- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType{ //callNative 为约定好的协议头,若是是,则页面不进行跳转 if ([request.URL.scheme isEqualToString:@"callNative"]) { NSlog(@"Hello World"); return NO; } //不是自定义协议头,跳转页面 return YES; }
##WKWebView 苹果自iOS八、OS X 10.10推荐使用WKWebView
来代替原先的UIWebView
,WKWebView
拥有更快的加载速度和性能,更低的内存占用,同时更细致的代理分类来知足不一样须要的调用。web
Native调用JS,使用方法evaluateJavaScript:completionHandler:
来解释执行脚本。app
//javaScriptString要执行的js方法 //completionHandler执行结束回调或者发生错误时回调 - (void)evaluateJavaScript:(NSString *)javaScriptString completionHandler:(void (^)(id, NSError *error))completionHandler;
JS调用Native,经过代理WKScriptMessageHandler来实现调用。框架
#import "WKWVController.h" #import <WebKit/WebKit.h> @interface WKWVController ()<WKUIDelegate,WKScriptMessageHandler> @property (strong, nonatomic) WKWebView *webView; @end @implementation WKWVController - (void)viewDidLoad { [super viewDidLoad]; // js配置 WKUserContentController *userContentController = [[WKUserContentController alloc] init]; //监听方法名 [userContentController addScriptMessageHandler:self name:@"jsCallOC"]; // WKWebView的配置 WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init]; configuration.userContentController = userContentController; // 显示WKWebView _webView = [[WKWebView alloc] initWithFrame:[UIScreen mainScreen].bounds configuration:configuration]; _webView.UIDelegate = self; // 设置WKUIDelegate代理 [self.view addSubview:_webView]; NSURL *url = [[NSBundle mainBundle] URLForResource:@"index" withExtension:@"html"]; NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url]; [_webView loadRequest:urlRequest]; } // WKScriptMessageHandler protocol? - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message { NSLog(@"方法名:%@", message.name); NSLog(@"参数:%@", message.body); // 方法名 NSString *methods = [NSString stringWithFormat:@"%@", message.name]; SEL selector = NSSelectorFromString(methods); // 调用方法 if ([self respondsToSelector:selector]) { [self performSelector:selector withObject:message.body]; } else { NSLog(@"未实行方法:%@", methods); } } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; } - (void)jsCallOC{ [self.webView evaluateJavaScript:@"wkNativeCallJS('嘿嘿')" completionHandler:^(id _Nullable data, NSError * _Nullable error) { NSLog(@"我执行完毕"); }]; }
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>网页</title> </head> <body> <button onclick="wkWebViewTestClick()" style="height: 100px;width: 200px;">点我调用native方法</button> function wkNativeCallJS(info){ //wkwebview 不直接使用js的alert 显示不了 //http://stackoverflow.com/questions/34185339/wkwebview-javascript-confirm-and-alert-not-working console.log(info); } function wkWebViewTestClick(){ // 复杂数据 var list = [1,2,3]; var dict = {"name":"阳君", "qq":"937447974"}; // JS通知WKWebView,jsCallOC即为在controller中注册的方法名称 window.webkit.messageHandlers.jsCallOC.postMessage(dict); } </script> </body> </html>
##JavaScriptCore方式相互调用 在iOS7.0中苹果公司增长了JS利器JavaScriptCore
框架,JavaScriptCore
提供了不少灵活的本地OC与JS的交互方式,经过JSContext
和JSValue
来完成的,JSContext
是一个WebView中js代码运行环境,js能够经过JSContext
以block
和经过继承JSExport
代理,自定义实现代理方法。post
#import "WVController.h" #import <JavaScriptCore/JavaScriptCore.h> @protocol JSObjcDelegate <JSExport> -(void)logInfo:(NSString*)info; @end @interface WVController ()<JSObjcDelegate> @property (weak, nonatomic) IBOutlet UIWebView *wv; @property (nonatomic, strong) JSContext *jsContext; @end @implementation WVController - (void)viewDidLoad { [super viewDidLoad]; NSString* path = [[NSBundle mainBundle]pathForResource:@"index" ofType:@"html"]; NSURL* url = [NSURL URLWithString:path]; NSURLRequest* request = [NSURLRequest requestWithURL:url]; [self.wv loadRequest:request]; } //oc调用js - (IBAction)callJSMethod:(id)sender { [self.wv stringByEvaluatingJavaScriptFromString:@"wvNativeCallJS()"]; } //使用url拦截 -(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{ if ([request.URL.scheme isEqualToString:@"callnative"]) { NSLog(@"hello world"); return false; } return true; } - (void)webViewDidFinishLoad:(UIWebView *)webView { //获取上下文对象 self.jsContext = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]; self.jsContext[@"Objc"] = self; self.jsContext.exceptionHandler = ^(JSContext *context, JSValue *exceptionValue) { context.exception = exceptionValue; NSLog(@"异常信息:%@", exceptionValue); }; //直接使用block方式执行oc方法 self.jsContext[@"logHello"] = ^(){ NSLog(@"hello"); }; } //使用代理接口方式执行native方法 -(void)logInfo:(NSString *)info{ NSLog(@"js传来的参数%@",info); JSValue* callback = self.jsContext[@"wvNativeCallJS"]; [callback callWithArguments:nil]; } @end
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>网页</title> </head> <body> //1 <button onclick="Objc.logInfo('哈哈')" style="height: 100px;width: 200px;">点我调用native方法</button> //2 <!-- <button onclick="logHello()" style="height: 100px;width: 200px;">点我调用native方法</button>--> <script type="text/javascript"> function wvNativeCallJS(){ alert("wvController"); } </script> </body> </html>
DEMO:下载Demo
参考: