##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
參考: