其實一直想給大家整理一下JS與OC的交互,但是沒有合適的機會,今天借著微信小應用的發布,以及以后H5必定越來越流行,所以給大家整理一下.
交互方式有三種:
1.UIWebviewDelegate2.javaScriptCore3.WebViewJavascriptBridge按照排序給大家介紹一下,我推薦前兩種方法,第三種需要依賴第三方框架,并且不一定能攔截成功,所以著重介紹前兩種,第三種知道怎么操作就行了第一種也是最簡單的一種,我在實際項目中就用的這個方法,根據UIWebviewDelegate的代理方法進行攔截
1 | -(BOOL)webView:(UIWebView *)webViewshouldStartLoadWithRequest:(NSURLRequest *)requestnavigationType:(UIWebViewNavigationType)navigationType{ |
點擊新聞按鈕,根據shouldStartLoadWithRequest這個方法,打印出返回的url地址為
1234567891011 | -(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)requestnavigationType:(UIWebViewNavigationType)navigationType{ NSString *requestStr= [request.URLabsoluteString]; NSLog(@"%@",requestStr);//判斷返回的url是否包含news這個字符串,如果有進入if判斷,進行攔截,如果沒有,則return YES,放行; NSRangenewRange =[[requestStrlowercaseString]rangeOfString:@"news"]; if(newRange.length> 0){ //進行你需要的操作 returnNO; } returnYES;} |
這個是iOS7之后蘋果推出的一個JS于OC交互的一個框架,極大的方便了我們對js的操作
123456789101112131415161718192021 | 相關的幾個類/*JS執行的環境,同時也通過JSVirtualMachine管理著所有對象的生命周期,每個JSValue都和JSContext相關聯并且強引用context。*/#import "JSContext.h"/*JS對象在JSVirtualMachine中的一個強引用,其實就是Hybird對象。我們對JS的操作都是通過它。并且每個JSValue都是強引用一個context。同時,OC和JS對象之間的轉換也是通過它*/#import "JSValue.h"/*JS和OC對象的內存管理輔助對象。由于JS內存管理是垃圾回收,并且JS中的對象都是強引用,而OC是引用計數。如果雙方相互引用,勢必會造成循環引用,而導致內存泄露。我們可以用JSManagedValue保存JSValue來避免。*/#import "JSManagedValue.h"/*JS運行的虛擬機,有獨立的堆空間和垃圾回收機制。*/#import "JSVirtualMachine.h"/*一個協議,如果JS對象想直接調用OC對象里面的方法和屬性,那么這個OC對象只要實現這個JSExport協議就可以了。*/#import "JSExport.h" |
接下來就是如何去通過js來調用oc的方法了
1 | //首先你要在本地的html文件里注冊一個按鈕,按鈕的打擊名字jsButton |
JavaScriptCore測試頁面
JavaScript12345678910 | //首先你要在本地的html文件里注冊一個按鈕,按鈕的打擊名字jsButton<!DOCTYPEHTML><htmllang="zh-CN"> <body> <p>JavaScriptCore測試頁面</p> <body> <buttononclick="jsButton()">JS按鈕</button> </body></html> |
12345678910111213141516 | //然后在加載完成的方法里通過JSContext來獲取相應操作的key值.key值是html文件里點擊方法的名字,并且調用你需要的操作- (void)webViewDidFinishLoad:(UIWebView *)webView{ JSContext *context= [self.webViewvalueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]; context[@"jsButton"]= ^{ //在這里調用你需要的操作 UIAlertController *alert= [UIAlertControlleralertControllerWithTitle:@"點擊了JS按鈕"message:@""preferredStyle:(UIAlertControllerStyleAlert)]; UIAlertAction *sureAlertAction= [UIAlertActionactionWithTitle:@"OK"style:(UIAlertActionStyleDefault)handler:^(UIAlertAction *_Nonnull action){ }]; [alertaddAction:sureAlertAction]; [selfpresentViewController:alertanimated:YEScompletion:^{ }]; }; } |
第三種方法是通過WebViewJavascriptBridge這個第三方庫,把js和oc之間搭建一個橋,來實現相互通信,這個是我最不推薦的一種方法,因為他需要依賴第三方庫來實現,通過互相注冊方法,增加代碼量并且并不是每次方法都能注冊上,有一定的失敗幾率,由于不推薦,所以就安排在最后,不做太詳細的解釋
3.1創建webview
1234567 | UIWebView*webView =[[UIWebViewalloc]initWithFrame:self.view.bounds]; [self.viewaddSubview:webView]; NSString *path= [[NSBundlemainBundle]pathForResource:@"JSBridge"ofType:@"html"]; NSURL *baseURL= [NSURLfileURLWithPath:[[NSBundlemainBundle]bundlePath]]; NSString *htmlString= [NSStringstringWithContentsOfFile:pathencoding:NSUTF8StringEncodingerror:nil]; [webViewloadHTMLString:htmlStringbaseURL:baseURL]; [self.viewaddSubview:webView]; |
3.2創建WebViewJavascriptBridge
123 | [WebViewJavascriptBridgeenableLogging];_bridge =[WebViewJavascriptBridgebridgeForWebView:webView];[_bridgesetWebViewDelegate:self]; |
3.3注冊js要調用Native
123 | //handlerName:需要調用js的名字//handler:需要oc進行的操作-(void)registerHandler:(NSString *)handlerNamehandler:(WVJBHandler)handler{ |
1234567891011 | [_bridgeregisterHandler:@"scanClick"handler:^(iddata,WVJBResponseCallback responseCallback){ //需要進行的操作 UIAlertController *alert= [UIAlertControlleralertControllerWithTitle:@"點擊了按鈕"message:@""preferredStyle:(UIAlertControllerStyleAlert)]; UIAlertAction *sureAlertAction= [UIAlertActionactionWithTitle:@"OK"style:(UIAlertActionStyleDefault)handler:^(UIAlertAction *_Nonnull action){ }]; [alertaddAction:sureAlertAction]; [selfpresentViewController:alertanimated:YEScompletion:^{ }]; }]; |
demo地址
新聞熱點
疑難解答