如今移動端的業務大多與web 相互的交集,爲了更好更快的配合線上的業務,web 混合 開發 是移動人員具有的基礎能力 在這,我總結下 我從幾家公司中本身所學習的web 和 oc 交互的知識:html
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的使用方式 那麼 如今我就繼續往下面走 代理方法什麼的 我就不寫了 畢竟相對來講都比較基礎微信
####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的獲取同樣 用字符串接受 而後本身作處理就行了
寫到這個就是很牛逼了,由於 以上代碼 太複雜 ,用這個 賊簡單 講講使用:
`
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 回調封裝的,若是個人總結 能給你幫助,幫忙點個喜歡 謝謝
武漢的天氣太熱 .... 我要去沖澡
本次發佈是摘自我的的簡書,現轉移到掘金