iOS與JS交互之WKWebView-協(xié)議攔截

級別:★★☆☆☆
標簽:「iOS與JS交互」「WKWebView與JS交互」「WKWebView攔截協(xié)議」
作者: Xs·H
審校: QiShare團隊

先解釋下標題:“iOS與JS交互”悯搔。iOS指iOS原生代碼(文章只有OC示例)挑秉,JS指WEB前端(不單指JavaScript)卸伞,交互指JS調(diào)用iOSiOS調(diào)用JS已维。
作者將iOS與JS交互總結(jié)成了6種方式,并將逐一介紹。目錄如下:


本文介紹通過 WKWebView協(xié)議攔截的方式實現(xiàn)iOSJS交互。
WKWebViewApple在iOS8推出的Webkit框架中的負責網(wǎng)頁的渲染與展示的類案怯,相比UIWebView速度更快,占用內(nèi)存更少澎办,支持更多的HTML特性嘲碱。

一、JS調(diào)用iOS:
  • 實現(xiàn)邏輯:點擊JS的登錄按鈕局蚀,JS將登錄成功后的token數(shù)據(jù)傳遞給iOS麦锯,iOS將收到的數(shù)據(jù)展示出來。

  • 實現(xiàn)效果:


    JS調(diào)用iOS實現(xiàn)效果
  • JS代碼:

//! 登錄按鈕
<button onclick = "login()" style = "font-size: 18px;">登錄</button>
//! 登錄
function login() {
  var token = "js_tokenString";
  loginSucceed(token);
}

//! 登錄成功
function loginSucceed(token) {
  var action = "loginSucceed";
  jsToOc(action, token);
}

//! JS調(diào)用OC入口
function jsToOc(action, params) {
  var url = "jsToOc://" + action + "?" + params;
  loadURL(url);
}

//! 加載URL
function loadURL(url) {
  window.location.href = url;
}
  • iOS代碼:
#pragma mark - WKNavigationDelegate

//! WKWeView在每次加載請求前會調(diào)用此方法來確認是否進行請求跳轉(zhuǎn)
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
    
    if ([navigationAction.request.URL.scheme caseInsensitiveCompare:@"jsToOc"] == NSOrderedSame) {
        [WKWebViewInterceptController showAlertWithTitle:navigationAction.request.URL.host message:navigationAction.request.URL.query cancelHandler:nil];
        decisionHandler(WKNavigationActionPolicyCancel);
    }
    else {
        decisionHandler(WKNavigationActionPolicyAllow);
    }
}
  • 實現(xiàn)原理:
    1琅绅、JS與iOS約定好jsToOc協(xié)議扶欣,用作JS在調(diào)用iOS時url的scheme
    2、JS在登錄成功后加載含有token數(shù)據(jù)的url:(jsToOc://loginSucceed?js_tokenString)料祠;
    3骆捧、iOS的WKWebView在請求跳轉(zhuǎn)前會調(diào)用-webView:decidePolicyForNavigationAction:decisionHandler:方法來確認是否允許跳轉(zhuǎn);
    4髓绽、iOS在此方法內(nèi)截取jsToOc協(xié)議獲取JS傳過來的數(shù)據(jù)敛苇,用UIAlertController顯示出來,并通過decisionHandler不允許此請求跳轉(zhuǎn)顺呕。

PS1:除了顯示截取到的數(shù)據(jù)枫攀,iOS還可以將navigationAction.request.URL.host看作JS想調(diào)用的方法名,將navigationAction.request.URL.query看作該方法的參數(shù)集株茶,從而體現(xiàn)出JS調(diào)用iOS的概念来涨。
PS2:在-webView:decidePolicyForNavigationAction:decisionHandler:方法中一定要調(diào)用decisionHandler回調(diào)來制定允許請求跳轉(zhuǎn)WKNavigationActionPolicyAllow或者不允許跳轉(zhuǎn)WKNavigationActionPolicyAllow,不然會崩潰启盛。


二扫夜、iOS調(diào)用JS:
  • 實現(xiàn)邏輯:點擊iOS的登錄按鈕,iOS將登錄成功后的token數(shù)據(jù)傳遞給JS驰徊,JS將收到的數(shù)據(jù)展示出來。

  • 實現(xiàn)效果:


    iOS調(diào)用JS實現(xiàn)效果
  • iOS代碼:

//! 登錄按鈕
UIBarButtonItem *loginBtnItem = [[UIBarButtonItem alloc] initWithTitle:@"登錄" style:UIBarButtonItemStylePlain target:self action:@selector(login:)];
self.navigationItem.rightBarButtonItems = @[loginBtnItem];
//! 登錄方法
- (void)login:(id)sender {
    
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [self.webView evaluateJavaScript:@"ocToJs('loginSucceed', 'oc_tokenString')" completionHandler:^(id response, NSError *error) {}];
    });
}
  • JS代碼:
//! iOS調(diào)用JS入口
function ocToJs(action, params) {
  document.getElementById("returnValue").innerHTML = action + '?' + params;
}
//! iOS調(diào)用JS數(shù)據(jù)顯示框
<div id = "returnValue" style = "font-size: 18px; border: 1px dotted; height: 50px;"> </div>
  • 實現(xiàn)原理:
    1堕阔、iOS與JS約定好ocToJs方法棍厂,用作iOS在調(diào)用JS時的入口方法;
    2超陆、iOS在登錄成功后以loginSucceedoc_tokenString為參數(shù)拼接JS代碼ocToJs('loginSucceed', 'oc_tokenString');
    3牺弹、iOS使用WKWebView的-evaluateJavaScript:completionHandler:方法執(zhí)行拼接好的JS代碼;
    3时呀、JS在ocToJs方法中將iOS傳過來的數(shù)據(jù)顯示在div元素中张漂;
    4、iOS通過completionHandler收到JS中ocToJs方法的回調(diào)谨娜。

PS:WKWebView的-evaluateJavaScript:completionHandler:方法可以執(zhí)行JS代碼航攒。但只有在整個webView加載完成之后調(diào)用此方法才會有響應(yīng)。比如:我們可以通過如下方式獲取JS的標題趴梢。

//! WKWebView在每次加載請求完成后會調(diào)用此方法
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
    
    [webView evaluateJavaScript:@"document.title" completionHandler:^(NSString *title, NSError *error) {
        self.title = title;
    }];
}

續(xù)篇:iOS與JS交互之WKWebView-WKScriptMessageHandler協(xié)議


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末漠畜,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子坞靶,更是在濱河造成了極大的恐慌憔狞,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,639評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件彰阴,死亡現(xiàn)場離奇詭異瘾敢,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評論 3 385
  • 文/潘曉璐 我一進店門簇抵,熙熙樓的掌柜王于貴愁眉苦臉地迎上來庆杜,“玉大人,你說我怎么就攤上這事正压⌒栏#” “怎么了?”我有些...
    開封第一講書人閱讀 157,221評論 0 348
  • 文/不壞的土叔 我叫張陵焦履,是天一觀的道長拓劝。 經(jīng)常有香客問我,道長嘉裤,這世上最難降的妖魔是什么郑临? 我笑而不...
    開封第一講書人閱讀 56,474評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮屑宠,結(jié)果婚禮上厢洞,老公的妹妹穿的比我還像新娘。我一直安慰自己典奉,他們只是感情好躺翻,可當我...
    茶點故事閱讀 65,570評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著卫玖,像睡著了一般公你。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上假瞬,一...
    開封第一講書人閱讀 49,816評論 1 290
  • 那天陕靠,我揣著相機與錄音,去河邊找鬼脱茉。 笑死剪芥,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的琴许。 我是一名探鬼主播税肪,決...
    沈念sama閱讀 38,957評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼榜田!你這毒婦竟也來了寸认?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,718評論 0 266
  • 序言:老撾萬榮一對情侶失蹤串慰,失蹤者是張志新(化名)和其女友劉穎偏塞,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體邦鲫,經(jīng)...
    沈念sama閱讀 44,176評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡灸叼,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,511評論 2 327
  • 正文 我和宋清朗相戀三年神汹,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片古今。...
    茶點故事閱讀 38,646評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡屁魏,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出捉腥,到底是詐尸還是另有隱情氓拼,我是刑警寧澤,帶...
    沈念sama閱讀 34,322評論 4 330
  • 正文 年R本政府宣布抵碟,位于F島的核電站桃漾,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏拟逮。R本人自食惡果不足惜撬统,卻給世界環(huán)境...
    茶點故事閱讀 39,934評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望敦迄。 院中可真熱鬧恋追,春花似錦、人聲如沸罚屋。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,755評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽脾猛。三九已至撕彤,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間尖滚,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,987評論 1 266
  • 我被黑心中介騙來泰國打工瞧柔, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留漆弄,地道東北人。 一個月前我還...
    沈念sama閱讀 46,358評論 2 360
  • 正文 我出身青樓造锅,卻偏偏與公主長得像撼唾,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子哥蔚,可洞房花燭夜當晚...
    茶點故事閱讀 43,514評論 2 348