iOS WKWebView JS 與 原生交互

一些說(shuō)明:
在iOS開(kāi)發(fā)中難免會(huì)用到網(wǎng)頁(yè)窗悯,在iOS 8以前区匣,我們更喜歡使用UIWebView,但是UIWebView有很多弊端蒋院,首先它有一個(gè)最讓人頭疼的問(wèn)題就是內(nèi)存會(huì)暴增亏钩,并且釋放不掉,而且蘋果開(kāi)放出來(lái)的接口相對(duì)較少欺旧,目前用Xcode 9進(jìn)行iOS開(kāi)發(fā)姑丑,其支持最低的系統(tǒng)版本號(hào)為iOS 9.0,目前所在的公司也并沒(méi)有要求對(duì)iOS 8.0以前版本進(jìn)行適配于是辞友,在新的項(xiàng)目中打算摒棄UIWebView而采用基于WebKit的WKWebView栅哀。

看完這篇博客你將學(xué)到:

  • 如何創(chuàng)建一個(gè)WKWebView
  • WK中JS怎么去調(diào)用OC方法
  • WK中怎么用OC調(diào)用js代碼

創(chuàng)建一個(gè)WKWebView

此部分相對(duì)簡(jiǎn)單,我們直接看代碼:

//創(chuàng)建一個(gè)控制器称龙,在控制器的ViewDidLoad方法中我們寫在如下代碼
- (void)viewDidLoad {
    [self.view addSubview:self.weWebView];
    // 此處加載的是本地HTML文件
    NSString *path = [[NSBundle mainBundle] pathForResource:@"index" ofType:@"html"];
    if (path) {
        NSURL *fileURL = [NSURL fileURLWithPath:path];
        [self.weWebView loadRequest:[NSURLRequest requestWithURL:fileURL]];
    }
}

// 懶加載創(chuàng)建一個(gè)WKWebView
- (WKWebView *)wkWebView {
    if (!_wkWebView) {
        // 進(jìn)行配置控制器
        WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
        // 實(shí)例化對(duì)象
        configuration.userContentController = [WKUserContentController new];
        // 調(diào)用JS方法
        [configuration.userContentController addScriptMessageHandler:self name:@"btnClick"];
        // 進(jìn)行偏好設(shè)置
        WKPreferences *preferences = [WKPreferences new];
        preferences.javaScriptCanOpenWindowsAutomatically = YES;
        preferences.minimumFontSize = 40.0;
        configuration.preferences = preferences;
        // 初始化WKWebView
        _weWebView = [[WKWebView alloc]initWithFrame:CGRectMake(0, 64, APP_SCREEN_WIDTH, APP_SCREEN_HEIGHT) configuration:configuration];
    }
    return _wkWebView;
}

以上代碼就能創(chuàng)建一個(gè)簡(jiǎn)單的WKWebView下面我們來(lái)看看JS 和 OC 之間是怎么進(jìn)行交互的

JS調(diào)用OC

js會(huì)通過(guò)以下方法調(diào)用原生方法

window.webkit.messageHandlers.<#對(duì)象名#>.postMessage(<#參數(shù)#>)

在原生中我們只要實(shí)現(xiàn)WKScriptMessageHandler的代理方法就行了留拾,值得注意的是參數(shù)name需要與上述代碼中對(duì)象名一致

// 添加scriptMessageHandler
- (void)addScriptMessageHandler:(id <WKScriptMessageHandler>)scriptMessageHandler name:(NSString *)name;

最后在

- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message;

這個(gè)方法中獲取做下判斷響應(yīng)對(duì)應(yīng)的方法即可,下面奉上事例代碼:

// 初始化WKWebView鲫尊,在實(shí)例化WKWebViewConfiguration對(duì)象的時(shí)候我們同時(shí)添加scriptMessageHandler
 //進(jìn)行配置控制器
        WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
        //實(shí)例化對(duì)象
        configuration.userContentController = [WKUserContentController new];
        //調(diào)用JS方法
        [configuration.userContentController addScriptMessageHandler:self name:@"btnClick"];

#pragma mark - WKScriptMessageHandler
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
    if ([message.name isEqualToString:@"btnClick"]) {
        NSDictionary *jsData = message.body;
        NSLog(@"%@", message.name, jsData);
        //讀取js function的字符串
        NSString *jsFunctionString = jsData[@"result"];
        //拼接調(diào)用該方法的js字符串(convertDictionaryToJson:方法將NSDictionary轉(zhuǎn)成JSON格式的字符串)
        NSString *jsonString = [NSDictionary convertDictionaryToJson:@{@"test":@"123", @"data":@"666"}];
        NSString *jsCallBack = [NSString stringWithFormat:@"(%@)(%@);", jsFunctionString, jsonString];
        //執(zhí)行回調(diào)
        [self.weWebView evaluateJavaScript:jsCallBack completionHandler:^(id _Nullable result, NSError * _Nullable error) {
            if (error) {
                NSLog(@"err is %@", error.domain);
            }
        }];
    }
}

以上需要注意的是痴柔,由于message的body只能是 NSNumber, NSString, NSDate, NSArray, NSDictionary, NSNull這幾種類型,可以看下圖蘋果官方注釋疫向,所以我們無(wú)法將js函數(shù)直接傳給原生咳蔚,在需要進(jìn)行回調(diào)的環(huán)境下,我們要將js回調(diào)函數(shù)轉(zhuǎn)成String后再傳給原生搔驼,再由原生獲取后進(jìn)行相關(guān)回調(diào)操作谈火,實(shí)際上這是已經(jīng)進(jìn)行了動(dòng)態(tài)js注入(執(zhí)行回調(diào)方法)


注意事項(xiàng).png

OC調(diào)用JS

動(dòng)態(tài)注入js方法就像對(duì)比較簡(jiǎn)單了,我們只要使用相應(yīng)方法即可匙奴。

- (void)evaluateJavaScript:(NSString *)javaScriptString completionHandler:(void (^ _Nullable)(_Nullable id, NSError * _Nullable error))completionHandler;

下面奉上一個(gè)事例代碼

// 此處是設(shè)置需要調(diào)用的js方法以及將對(duì)應(yīng)的參數(shù)傳入堆巧,需要以字符串的形式
NSString *jsFounction = [NSString stringWithFormat:@"getAppConfig('%@')", APP_CHANNEL_ID];
// 調(diào)用API方法
    [self.weexWebView evaluateJavaScript:jsFounction completionHandler:^(id object, NSError * _Nullable error) {
        NSLog(@"obj:%@---error:%@", object, error);
    }];

最后貼上測(cè)試HTML代碼

<html>
<header>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <script type="text/javascript">

        function btnClick() {
          test({
            testString: "testString",
            result: function(data) {
              //理論上傳過(guò)來(lái)的是轉(zhuǎn)成JSON格式字符串的MAP,需要統(tǒng)一一下KEY值
            // 此處demo相當(dāng)與document.getElementById("demo")
              demo.innerHTML = data["data"];
            }
          })
        }

        function test(testData) {
          var testStr = testData.testString
          var result = testData.result
          //此處不能直接將回調(diào)函數(shù)傳給iOS需要將回調(diào)函數(shù)轉(zhuǎn)成字符串,其他的保持不變即可
          testData.result = result.toString()
          window.webkit.messageHandlers.btnClick.postMessage(testData);
        }

    </script>
</header>
<body bgcolor="red">
    <h2> js回調(diào)Test </h2>
    <br/>
    <br/>
    <button type="button" onclick="btnClick()">test回調(diào)</button>
    <br/>
    <br/>
    <p id="demo">暫無(wú)回調(diào)</p>
</body>
</html>
回調(diào)前.png
回調(diào)后.png

最后,本人水平有限如有錯(cuò)誤歡迎指正>_<

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市谍肤,隨后出現(xiàn)的幾起案子啦租,更是在濱河造成了極大的恐慌,老刑警劉巖荒揣,帶你破解...
    沈念sama閱讀 216,470評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件篷角,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡系任,警方通過(guò)查閱死者的電腦和手機(jī)恳蹲,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)俩滥,“玉大人嘉蕾,你說(shuō)我怎么就攤上這事∷桑” “怎么了错忱?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,577評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)挂据。 經(jīng)常有香客問(wèn)我以清,道長(zhǎng),這世上最難降的妖魔是什么崎逃? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,176評(píng)論 1 292
  • 正文 為了忘掉前任掷倔,我火速辦了婚禮,結(jié)果婚禮上个绍,老公的妹妹穿的比我還像新娘勒葱。我一直安慰自己,他們只是感情好障贸,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,189評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布错森。 她就那樣靜靜地躺著,像睡著了一般篮洁。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上殃姓,一...
    開(kāi)封第一講書(shū)人閱讀 51,155評(píng)論 1 299
  • 那天袁波,我揣著相機(jī)與錄音,去河邊找鬼蜗侈。 笑死篷牌,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的踏幻。 我是一名探鬼主播枷颊,決...
    沈念sama閱讀 40,041評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了夭苗?” 一聲冷哼從身側(cè)響起信卡,我...
    開(kāi)封第一講書(shū)人閱讀 38,903評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎题造,沒(méi)想到半個(gè)月后傍菇,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,319評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡界赔,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,539評(píng)論 2 332
  • 正文 我和宋清朗相戀三年搀愧,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了遇骑。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,703評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖拐揭,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情茬贵,我是刑警寧澤胀莹,帶...
    沈念sama閱讀 35,417評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站瞧挤,受9級(jí)特大地震影響锡宋,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜特恬,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,013評(píng)論 3 325
  • 文/蒙蒙 一执俩、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧癌刽,春花似錦役首、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,664評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至远荠,卻和暖如春矮固,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背譬淳。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,818評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工档址, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人邻梆。 一個(gè)月前我還...
    沈念sama閱讀 47,711評(píng)論 2 368
  • 正文 我出身青樓守伸,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親浦妄。 傳聞我的和親對(duì)象是個(gè)殘疾皇子尼摹,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,601評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容

  • 前言 關(guān)于UIWebView的介紹,相信看過(guò)上文的小伙伴們惠赫,已經(jīng)大概清楚了吧把鉴,如果有問(wèn)題,歡迎提問(wèn)儿咱。 本文是本系列...
    Dark_Angel閱讀 28,867評(píng)論 67 291
  • 前言 iOS開(kāi)發(fā)中,用來(lái)顯示一個(gè)html頁(yè)钳宪、H5頁(yè)揭北,經(jīng)常會(huì)用的一個(gè)控件是WebView。說(shuō)到WebView吏颖,你知道...
    Dark_Angel閱讀 23,430評(píng)論 31 287
  • 云淡風(fēng)輕搔体,飛鳥(niǎo)過(guò)、江海靜享安寧半醉。萬(wàn)山紅遍疚俱,光染澗水承明。湖里魚(yú)兒依舊是缩多,游得興致顯機(jī)靈呆奕。路邊亭。腿閑就坐衬吆,何等真誠(chéng)...
    木貞ma閱讀 294評(píng)論 6 3
  • 今天讀到的這篇可以說(shuō)是耳熟能詳梁钾,但讓我更感興趣的是關(guān)于賀知章的一些軼事。 回鄉(xiāng)偶書(shū) 賀知章 少小離鄉(xiāng)老大回逊抡,鄉(xiāng)音...
    慢慢樹(shù)閱讀 215評(píng)論 0 0
  • 我們會(huì)在什么情況下姆泻,會(huì)去懷疑人生。懷疑人生到底在懷疑什么秦忿? 1.當(dāng)我們?cè)诿悦B笊洌洌瑹o(wú)助的時(shí)候灯谣,...
    亦想亦開(kāi)閱讀 676評(píng)論 0 0