鏈接:http://ios.jobbole.com/89330/
其實一直想給大家整理一下JS與OC的交互,但是沒有合適的機會,今天借著微信小應用的發布,以及以后H5必定越來越流行,所以給大家整理一下.
交互方式有三種:
1.UIWebviewDelegate
2.JavaScriptCore
3.WebViewJavascriptBridge
按照排序給大家介紹一下,我推薦前兩種方法,第三種需要依賴第三方框架,并且不一定能攔截成功,所以著重介紹前兩種,第三種知道怎么操作就行了
1.UIWebviewDelegate
第一種也是最簡單的一種,我在實際項目中就用的這個方法,根據UIWebviewDelegate的代理方法進行攔截
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{
點擊新聞按鈕,根據shouldStartLoadWithRequest這個方法,打印出返回的url地址為
-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{
? ?NSString *requestStr = [request.URL absoluteString];
? ?NSLog(@"%@",requestStr);
//判斷返回的url是否包含news這個字符串,如果有進入if判斷,進行攔截,如果沒有,則return YES,放行;
? ?NSRange newRange = [[requestStr lowercaseString] rangeOfString:@"news"];
? ?if (newRange.length > 0) {
? ? ? //進行你需要的操作
? ? ? ?return NO;
? ?}
? ?return YES;
}
2.JavaScriptCore
這個是iOS7之后蘋果推出的一個JS于OC交互的一個框架,極大的方便了我們對js的操作
相關的幾個類
/*
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的方法了
//首先你要在本地的html文件里注冊一個按鈕,按鈕的打擊名字jsButton
JavaScriptCore測試頁面
//首先你要在本地的html文件里注冊一個按鈕,按鈕的打擊名字jsButton
JavaScriptCore測試頁面
? ?JS按鈕
//然后在加載完成的方法里通過JSContext來獲取相應操作的key值.key值是html文件里點擊方法的名字,并且調用你需要的操作
- (void)webViewDidFinishLoad:(UIWebView *)webView {
? ?JSContext *context = [self.webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
? ?context[@"jsButton"] = ^{
? ? ? ?//在這里調用你需要的操作
? ? ? ?UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"點擊了JS按鈕" message:@"" preferredStyle:(UIAlertControllerStyleAlert)];
? ? ? ?UIAlertAction *sureAlertAction = [UIAlertAction actionWithTitle:@"OK" style:(UIAlertActionStyleDefault) handler:^(UIAlertAction * _Nonnull action) {
? ? ? ?}];
? ? ? ?[alert addAction:sureAlertAction];
? ? ? ?[self presentViewController:alert animated:YES completion:^{
? ? ? ?}];
? ?};
}
3.WebViewJavascriptBridge
第三種方法是通過WebViewJavascriptBridge這個第三方庫,把js和oc之間搭建一個橋,來實現相互通信,這個是我最不推薦的一種方法,因為他需要依賴第三方庫來實現,通過互相注冊方法,增加代碼量并且并不是每次方法都能注冊上,有一定的失敗幾率,由于不推薦,所以就安排在最后,不做太詳細的解釋
3.1創建webview
UIWebView* webView = [[UIWebView alloc] initWithFrame:self.view.bounds];
? ?[self.view addSubview:webView];
? ?NSString *path = [[NSBundle mainBundle] pathForResource:@"JSBridge" ofType:@"html"];
? ?NSURL *baseURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]];
? ?NSString *htmlString = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
? ?[webView loadHTMLString:htmlString baseURL:baseURL];
? ?[self.view addSubview:webView];
3.2創建WebViewJavascriptBridge
[WebViewJavascriptBridge enableLogging];
_bridge = [WebViewJavascriptBridge bridgeForWebView:webView];
[_bridge setWebViewDelegate:self];
3.3注冊js要調用Native
//handlerName:需要調用js的名字
//handler:需要oc進行的操作
- (void)registerHandler:(NSString *)handlerName handler:(WVJBHandler)handler {
[_bridge registerHandler:@"scanClick" handler:^(id data, WVJBResponseCallback responseCallback) {
? ? ? ?//需要進行的操作
? ? ? ?UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"點擊了按鈕" message:@"" preferredStyle:(UIAlertControllerStyleAlert)];
? ? ? ?UIAlertAction *sureAlertAction = [UIAlertAction actionWithTitle:@"OK" style:(UIAlertActionStyleDefault) handler:^(UIAlertAction * _Nonnull action) {
? ? ? ?}];
? ? ? ?[alert addAction:sureAlertAction];
? ? ? ?[self presentViewController:alert animated:YES completion:^{
? ? ? ?}];
? ?}];
demo地址:https://github.com/summer7659/webview-js-oc-