JS 與 OC 中的交互

JS 與 OC 中的交互

如今移動端的業務大多與web 相互的交集,爲了更好更快的配合線上的業務,web 混合 開發 是移動人員具有的基礎能力 在這,我總結下 我從幾家公司中本身所學習的web 和 oc 交互的知識:html

UIWebVwe

UIWebView繼承與UIView,所以,其初始化方法和通常的View同樣,經過alloc和init進行初始化。 UIWebView 是用來加載加載網頁數據的一個框。UIWebView能夠用來加載pdf、word、doc 等等文件java

本地加載一個html 文件ios

- (void)viewDidLoad {
    [super viewDidLoad];
   
    //加載本地文件
    ///UIKIT_EXTERN API_DEPRECATED("No longer supported; please adopt WKWebView.", ios(2.0, 12.0))   iOS 12以後UIwebView 即將被廢棄
    UIWebView * web = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
    
    NSURL * url =  [[NSBundle mainBundle] URLForResource:@"baidu.html" withExtension:nil];
    NSURLRequest * request = [NSURLRequest requestWithURL:url];
    [web loadRequest:request];
    
    [self.view addSubview:web]; 
}
#pragma mark delegate
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
    return  YES;
}



-(void)webViewDidFinishLoad:(UIWebView *)webView
{
    self.title = [webView stringByEvaluatingJavaScriptFromString:@"document.title"];

}

複製代碼

直接根據連接加載網頁web

[web loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"www.baidu.com" relativeToURL:nil]]];

複製代碼

或者說 你根絕html 內容 直接加載 (項目中 本身作一個圖片加載連接地址 而後加載內容... ) 具體參照HTML標籤去處理數組

[self.webView loadHTMLString:@"<p>你所要表述的內容實質</p>" baseURL:nil];
複製代碼

再就是加載文件,好比 PDF Word文件等等 這些都是web 能作到的 例如bash

#pragma 以二進制數據的形式加載文件 
- (void)loadDataFile  {  
    // 最最多見的一種狀況  
    // 打開IE,訪問網站,提示你安裝Flash插件  
    // 若是沒有這個應用程序,是沒法用UIWebView打開對應的文件的  
       
    // 應用場景:加載從服務器上下載的文件,例如pdf,或者word,圖片等等文件  
    NSURL *fileURL = [[NSBundle mainBundle] URLForResource:@"iOS 7 Programming Cookbook.pdf" withExtension:nil];  
       
    NSURLRequest *request = [NSURLRequest requestWithURL:fileURL];  
    // 服務器的響應對象,服務器接收到請求返回給客戶端的  
    NSURLResponse *respnose = nil;  
       
    NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&respnose error:NULL];  
       
    NSLog(@"%@", respnose.MIMEType);  
       
    // 在iOS開發中,若是不是特殊要求,全部的文本編碼都是用UTF8  
    // 先用UTF8解釋接收到的二進制數據流  
    [self.webView loadData:data MIMEType:respnose.MIMEType textEncodingName:@"UTF8" baseURL:nil];  
}

// 本地方法:
//從本地加載
    NSString *thePath = [[NSBundle mainBundle] pathForResource:@"User_Guide" ofType:@"pdf"];
    
    if (thePath) {
        NSData *pdfData = [NSData dataWithContentsOfFile:thePath];
        [self.webView loadData:pdfData MIMEType:@"application/pdf" textEncodingName:@"utf-8" baseURL:nil];
    }
複製代碼

這個業務 樓主遇到過 作出的方式就是仿照微信去打開文件 而後去連接藍牙設備 打印等等...服務器

以上說述 都是webview的使用方式 那麼 如今我就繼續往下面走 代理方法什麼的 我就不寫了 畢竟相對來講都比較基礎微信

UIWebview 交互JS

####1如何處理 代碼攔截app

在iOS的工程代碼中 web 和 js 的交互 主要的進行方式是在ide

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType

這個代碼中
NSLog(@"%@",request); 對request 對象進行打印 會發現這個reque 展現的是一個 路由 <NSMutableURLRequest: 0x600001354220> { URL: file:///Users/chenjiazhen/Library/Developer/CoreSimulator/Devices/D3F41005-1A57-4DAF-B3CE-47A986C9B867/data/Containers/Bundle/Application/BAF7F1D0-DCE6-4388-B810-6929B34058FA/demo.app/baidu.html } 這個就是web的文件地址所在的地方

在此 就能作一個處理 就是 NSLog(@"schme ===== %@",request.URL.scheme); 在此,能夠處理web 中 js 交互不存在的交互方法 作攔截 固然,從這個地方也能夠制定本身的一套方案 想怎麼玩就怎麼玩 js 全部的響應 都會根據你的想法去執行。

####2 js 與 oc 的交互

NSLog(@"%@",request.URL.pathComponents);
複製代碼

此處是對js文件裏面的路徑的信息處理 好比 在此處 咱們傳遞一個字段 裏面增長一個getsum的參數。 那麼 在打印的地方就會出現

"/", getsum(1,3), Users, chenjiazhen, Library, Developer, CoreSimulator, Devices, "D3F41005-1A57-4DAF-B3CE-47A986C9B867", data, Containers, Bundle, Application, "B6FF5281-6954-45AB-935B-11626882C61B", "demo.app", "baidu.html" 相似於這樣的一個信息數組,那麼 就在getsum(1,3) 相似於這種調用方式 就會添加到這個信息數組中

就能拿到當前js 和 web 的交互數據了 而後 通過約定處理好後 oc 獲取方法名 和 傳遞參數 使用 如下的代碼 就能完成 js 調用 oc 的系統內容了

` [self performSelector:NSSelectorFromString(@"xxx") withObject:@"數據內容" afterDelay:0];

`

####3 oc 調用 js emmmmmm... 這個我以爲沒得必要詳細的去總結 由於 以前已經在博客內容裏面其實已經寫到了 self.title = [webView stringByEvaluatingJavaScriptFromString:@"document.title"]; 這個 就是 獲取js 的系統方法的title名,固然 這裏用的是最老套的方法 ,主要函數仍是 stringByEvaluatingJavaScriptFromString 固然 能夠根據內容繼續拓展 好比你想經過 oc 調用 js的函數
以alert爲例子 [webView stringByEvaluatingJavaScriptFromString:@"showAlert("你要來和我一塊兒玩嗎 ?")"]; 這裏 調用的就是js 的showAlert的方法 傳遞的信息技術括號內的內容

固然 如若 js 有數據信息返回 咱們就如title的獲取同樣 用字符串接受 而後本身作處理就行了

JavaScriptCore

寫到這個就是很牛逼了,由於 以上代碼 太複雜 ,用這個 賊簡單 講講使用:

`

JSContext * CONT  = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];

//建立一個全局的函數  也包括  調用js的方法參數
[CONT evaluateScript:@"var arr = ['haha','yes','baby']"];

//保存一段代碼塊
//當js 調用 方法的時候  這邊就會處理 包括參數啊什麼的
CONT[@"saveMyinfo"] = ^{
    //獲取參數
    NSArray * ager = [JSContext currentArguments];
    
};
複製代碼

`

這裏 縮減了不少的方法處理判斷,而後 咱們就是經過js 調用方法 在oc 中保存了一段代碼塊 ,js 調用 saveMyinfo 的時候,那麼 這個信息就反饋在了oc 的代碼中 咱們能夠獲取到系統參數啊什麼的,比以上 簡介不少,目前 我所看到的不少關於 js調用oc 的橋接封裝 都是這麼處理的 。固然 調用js 就是如上 evaluateScript這個方法,我就不過多的描述了。

以上 都是UIWebView 那麼繼續...

#WKWebView 不過多的介紹 iOS 都應該知道 這是Apple 對UIweb的優化 WKWebView:網頁的渲染與展現

注意: #import <WebKit/WebKit.h>
     //初始化
       _webView = [[WKWebView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT) configuration:config];
        // UI代理
        _webView.UIDelegate = self;
        // 導航代理
        _webView.navigationDelegate = self;
        // 是否容許手勢左滑返回上一級, 相似導航控制的左滑返回
        _webView.allowsBackForwardNavigationGestures = YES;
        //可返回的頁面列表, 存儲已打開過的網頁 
       WKBackForwardList * backForwardList = [_webView backForwardList];

        //        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://www.chinadaily.com.cn"]];
        //        [request addValue:[self readCurrentCookieWithDomain:@"http://www.chinadaily.com.cn"] forHTTPHeaderField:@"Cookie"];
        //        [_webView loadRequest:request];
        //頁面後退
        [_webView goBack];
        //頁面前進
         [_webView goForward];
        //刷新當前頁面
        [_webView reload];
        
        NSString *path = [[NSBundle mainBundle] pathForResource:@"JStoOC.html" ofType:nil];
        NSString *htmlString = [[NSString alloc]initWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
      //加載本地html文件
        [_webView loadHTMLString:htmlString baseURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]]];
複製代碼

WKWebViewConfiguration:爲添加WKWebView配置信息

//建立網頁配置對象
        WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
        
        // 建立設置對象
        WKPreferences *preference = [[WKPreferences alloc]init];
        //最小字體大小 當將javaScriptEnabled屬性設置爲NO時,能夠看到明顯的效果
        preference.minimumFontSize = 0;
        //設置是否支持javaScript 默認是支持的
        preference.javaScriptEnabled = YES;
        // 在iOS上默認爲NO,表示是否容許不通過用戶交互由javaScript自動打開窗口
        preference.javaScriptCanOpenWindowsAutomatically = YES;
        config.preferences = preference;
        
        // 是使用h5的視頻播放器在線播放, 仍是使用原生播放器全屏播放
        config.allowsInlineMediaPlayback = YES;
        //設置視頻是否須要用戶手動播放  設置爲NO則會容許自動播放
        config.requiresUserActionForMediaPlayback = YES;
        //設置是否容許畫中畫技術 在特定設備上有效
        config.allowsPictureInPictureMediaPlayback = YES;
        //設置請求的User-Agent信息中應用程序名稱 iOS9後可用
        config.applicationNameForUserAgent = @"ChinaDailyForiPad";
         //自定義的WKScriptMessageHandler 是爲了解決內存不釋放的問題
        WeakWebViewScriptMessageDelegate *weakScriptMessageDelegate = [[WeakWebViewScriptMessageDelegate alloc] initWithDelegate:self];
        //這個類主要用來作native與JavaScript的交互管理
        WKUserContentController * wkUController = [[WKUserContentController alloc] init];
        //註冊一個name爲jsToOcNoPrams的js方法
        [wkUController addScriptMessageHandler:weakScriptMessageDelegate  name:@"jsToOcNoPrams"];
        [wkUController addScriptMessageHandler:weakScriptMessageDelegate  name:@"jsToOcWithPrams"]; 
       config.userContentController = wkUController;
複製代碼

WKUserContentController:這個類主要用來作native與JavaScript的交互管理

//這個類主要用來作native與JavaScript的交互管理
        WKUserContentController * wkUController = [[WKUserContentController alloc] init];
        //註冊一個name爲jsToOcNoPrams的js方法,設置處理接收JS方法的代理
        [wkUController addScriptMessageHandler:self  name:@"jsToOcNoPrams"];
        [wkUController addScriptMessageHandler:self  name:@"jsToOcWithPrams"];
        config.userContentController = wkUController;
       //用完記得移除
       //移除註冊的js方法
        [[_webView configuration].userContentController removeScriptMessageHandlerForName:@"jsToOcNoPrams"];
       [[_webView configuration].userContentController removeScriptMessageHandlerForName:@"jsToOcWithPrams"];
複製代碼

WKScriptMessageHandler:這個協議類專門用來處理監聽JavaScript方法從而調用原生OC方法,和WKUserContentController搭配使用。

注意:遵照WKScriptMessageHandler協議,代理是由WKUserContentControl設置

   //經過接收JS傳出消息的name進行捕捉的回調方法
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{
    NSLog(@"name:%@\\\\n body:%@\\\\n frameInfo:%@\\\\n",message.name,message.body,message.frameInfo);
    //用message.body得到JS傳出的參數體
    NSDictionary * parameter = message.body;
    //JS調用OC
    if([message.name isEqualToString:@"jsToOcNoPrams"]){
        UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"js調用到了oc" message:@"不帶參數" preferredStyle:UIAlertControllerStyleAlert];
        [alertController addAction:([UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        }])];
        [self presentViewController:alertController animated:YES completion:nil];
        
    }else if([message.name isEqualToString:@"jsToOcWithPrams"]){
        UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"js調用到了oc" message:parameter[@"params"] preferredStyle:UIAlertControllerStyleAlert];
        [alertController addAction:([UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        }])];
        [self presentViewController:alertController animated:YES completion:nil];
    }
}

複製代碼

以上就是WKweb的一些介紹 和 詳細的使用方式了 ... 寫這麼多 感受腦殼都要爆炸了 ,我在總結下

oc 調用 js 
 [_webView evaluateJavaScript:@"你所須要的傳遞的參數 或者你響應的方法 " completionHandler:^(id _Nullable data, NSError * _Nullable error) {
 //下面是返回的回調信息
        NSLog(@"我是回調信息");
    }];
    
 js  調用 oc 
   //經過接收JS傳出消息的name進行捕捉的回調方法
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{
    NSLog(@"name:%@\\\\n body:%@\\\\n frameInfo:%@\\\\n",message.name,message.body,message.frameInfo);
    //用message.body得到JS傳出的參數體
    NSDictionary * parameter = message.body;
    //JS調用OC
    if([message.name isEqualToString:@"jsToOcNoPrams"]){
        UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"js調用到了oc" message:@"不帶參數" preferredStyle:UIAlertControllerStyleAlert];
        [alertController addAction:([UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        }])];
        [self presentViewController:alertController animated:YES completion:nil];
        
    }else if([message.name isEqualToString:@"jsToOcWithPrams"]){
        UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"js調用到了oc" message:parameter[@"params"] preferredStyle:UIAlertControllerStyleAlert];
        [alertController addAction:([UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        }])];
        [self presentViewController:alertController animated:YES completion:nil];
    }
}
複製代碼

以上就是業務中經常使用到得js oc 交互的總結,目前網上 不少的第三方封裝介紹對這些函數信息的封裝處理後 直接block 回調封裝的,若是個人總結 能給你幫助,幫忙點個喜歡 謝謝

武漢的天氣太熱 .... 我要去沖澡

本次發佈是摘自我的的簡書,現轉移到掘金

相關文章
相關標籤/搜索