本篇主要講的是UIWebView和JS的交互,在下一節會有wkWebView和JS交互的詳解https://www.cnblogs.com/llhlj/p/9144110.html
JS調用原生OC
方式一:url攔截,這里略過
注意:在iOS中攔截到的url scheme將全部轉化為小寫;
html中需要設置編碼,否則中文參數可能會出現編碼問題;
JS用打開一個iFrame的方式替代直接用document.location的方式,document.location 有一個很嚴重的問題,就是如果我們連續 2 次改 document.location 的話,在 delegate 方法中,只能截獲后面那次請求,前一次請求由於很快被替換掉,所以被忽略掉。
方式二:通過JavaScriptCore(iOS 7之后),用來做JS交互,因此JS與原生OC交互也變得簡單了許多。
//獲取js上下文,及本地添加js調用方法,一般情況下都放在-(void)webViewDidFinishLoad:(UIWebView *)webView方法里。
-(void)webViewDidFinishLoad:(UIWebView *)webView{ //獲取js上下文 self.jscontext = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]; //添加js代用方法 self.jscontext[@"octestFunc"]= ^(){ //oc邏輯 NSArray *array = [JSContext currentArguments]; for (NSString *value in array) { NSLog(@"收到js值:%@",value); } return @"oc";//也可以沒有返回值 }; //異常處理 當oc本地調用的js方法不存時,會打印異常信息,注意只有通過上下文調用的才會異常處理如oc調用js方式2、3 self.jscontext.exceptionHandler = ^(JSContext* context,JSValue *exceptionValue){ NSLog(@"異常信息:%@", exceptionValue); }; }
方式三:同方式二相似,通過JSExport協議
自定義協議
@protocol JSObjcDelegate<JSExport>//自定義協議 //自定義交互方法 -(id)getMessage:(id)msg; @end @interface WebViewController ()<UIWebViewDelegate,JSObjcDelegate> @property(nonatomic,strong)UIWebView *webView; @property(nonatomic,strong)JSContext *jscontext; @end
設置代理
-(void)webViewDidFinishLoad:(UIWebView *)webView{ //獲取js上下文 self.jscontext = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]; //設置代理 self.jscontext[@"ios"]= self; //異常處理 當oc本地調用的js方法不存時,會打印異常信息,注意只有通過上下文調用的才會異常處理如oc調用js方式2、3 self.jscontext.exceptionHandler = ^(JSContext* context,JSValue *exceptionValue){ NSLog(@"異常信息:%@", exceptionValue); }; }
代理方法的實現
//代理方法的實現 -(id)getMessage:(id)message{ NSLog(@"getMessage-------%@",message); return @"oc";//返回值可以沒有 }
OC調用JS
-(void)callJSFunc{ //方式1 // NSString *jsText = [NSString stringWithFormat:@"ocCallJSFunc('%@')",@"哈哈"]; // id value = [self.webView stringByEvaluatingJavaScriptFromString:jsText];//也可能沒有返回值 // NSLog(@"value-----%@",value); //方式2 // JSValue *callback = self.jscontext[@"ocCallJSFunc"]; // id value2 = [callback callWithArguments:@[@"222"]]; // NSLog(@"value2-----%@",value2); //方式3 NSString *jsText = @"ocCallJSFunc('222')"; id value3 = [self.jscontext evaluateScript:jsText]; NSLog(@"value3-----%@",value3); }
注意:stringByEvaluatingJavaScriptFromString是一個同步的方法,使用它執行JS方法時,如果JS 方法比較耗的時候,會造成界面卡頓。
官方推薦使用WKWebView(ios8)的evaluateJavaScript:completionHandler:代替這個方法。