iOS OC與JS交互(WebView監(jiān)聽事件)

在iOS應用的開發(fā)過程中,我們經(jīng)常會使用到WebView,當我們對WebView進行操作的時候,有時會需要進行源生的操作.那么我記下來就與大家分享一下OC與JS交互.

首先先說第一種方法,并沒有牽扯OC與JS交互,只是做攔截和跳轉(zhuǎn).

攔截跳轉(zhuǎn)的URL,跳轉(zhuǎn)源生界面(用起來感覺怪怪的,萬一URL更換了怎么辦.)
UIWebView
//UIWebViewDelegate
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
    NSString *url = request.URL.absoluteString;
    if ([url rangeOfString:@"需要跳轉(zhuǎn)源生界面的URL判斷"].location != NSNotFound) {
        //跳轉(zhuǎn)原生界面
        return NO;
    }
    return YES;
}
WKWebView
//使用WKWebview需要導入WebKit
#import <WebKit/WebKit.h>
//WKNavigationDelegate
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
    NSString *url = navigationAction.request.URL.absoluteString;
    if ([url rangeOfString:@"需要跳轉(zhuǎn)源生界面的URL判斷"].location != NSNotFound) {
        //跳轉(zhuǎn)原生界面
        
        //Cancel the navigation
        decisionHandler(WKNavigationActionPolicyCancel);
        return;
    }
    decisionHandler(WKNavigationActionPolicyAllow);
}

----------?↓↓↓↓↓↓?----------

OC與JS交互(WebView監(jiān)聽事件)

正入主題.

一.OC調(diào)用JS

1.UIWebView

①直接運行

NSString *jsStr = @"執(zhí)行的JS代碼";
[webView stringByEvaluatingJavaScriptFromString:jsStr];

②使用JavaScriptCore框架

#import <JavaScriptCore/JavaScriptCore.h>  
- (void)webViewDidFinishLoad:(UIWebView *)webView {
    //獲取webview中的JS內(nèi)容
    JSContext *context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
    NSString *runJS = @"執(zhí)行的JS代碼";
    //準備執(zhí)行的JS代碼
    [context evaluateScript:runJS];
}
2.WKWebView
[webView evaluateJavaScript:@"執(zhí)行的JS代碼" completionHandler:^(id _Nullable response, NSError * _Nullable error) {
  
}];

二.JS調(diào)用OC ??????

當網(wǎng)頁觸發(fā)某種操作,可以給App傳遞消息.比如WebView中購買某樣東西,點擊購買,需要獲取這件商品的訂單信息,并且需要App進行源生的支付.
這種方法需要你和后臺或者前端協(xié)商好一下,讓他們在執(zhí)行JS方法的時候,將你需要的數(shù)據(jù)放到你能拿到的位置.

下面簡單貼一個HTML文件.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>App與WebView交互</title>
</head>
<body>
<button style="width: 100%; height: 100px;" onclick="buttonClick()">點擊購買</button>
</body>
<script>
    //按鈕點擊事件
    function buttonClick() {
        //傳遞的信息
        var jsonStr = '{"id":"666", "message":"我是傳遞的數(shù)據(jù)"}';

        //UIWebView使用
        getMessage(jsonStr);

       //WKWebView使用
       //使用下方方法,會報錯,為使界面執(zhí)行邏輯通暢,因此使用try-catch
        try {
            window.webkit.messageHandlers.getMessage.postMessage(jsonStr)
        } catch(error) {
            console.log(error)
        }
    }
    function getMessage(json){
        //空方法
    }
</script>
</html>

window.webkit.messageHandlers.<方法名>.postMessage(<數(shù)據(jù)>)
JS端寫此方法的盆友可能會報錯,導致界面邏輯無法進行,因此使用try-catch就好了.

我在網(wǎng)頁上只寫了一個按鈕.點擊按鈕,會觸發(fā)buttonClick()方法.

UIWebView

在網(wǎng)頁加載完成的時候檢測JS方法執(zhí)行.

- (void)webViewDidFinishLoad:(UIWebView *)webView {
    //核心方法如下
    JSContext *content = [self.webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
    //此處的getMessage和JS方法中的getMessage名稱一致.
    content[@"getMessage"] = ^() {
        NSArray *arguments = [JSContext currentArguments];
        for (JSValue *jsValue in arguments) {
            NSLog(@"=======%@",jsValue);
        }
    };
}

由上方方法,當JS方法getMessage()執(zhí)行的時候,此方法回調(diào)的jsValue內(nèi)容就是我們需要的內(nèi)容.(HTML中JS傳遞的數(shù)據(jù))

WebView中的getMessage與HTML文件JS方法的getMessage名稱需保持一致.

WKWebView

實現(xiàn)WKScriptMessageHandler的代理方法.

//設置addScriptMessageHandler與JS對應方法名.并且設置<WKScriptMessageHandler>協(xié)議與協(xié)議方法
[[_webView configuration].userContentController addScriptMessageHandler:self name:@"getMessage"];

//WKScriptMessageHandler協(xié)議方法
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
    //code
    NSLog(@"name = %@, body = %@", message.name, message.body);
}

上方-addScriptMessageHandler:name:方法中name填寫的方法名必須與window.webkit.messageHandlers.<方法名>.postMessage(<數(shù)據(jù)>)中的方法名一致.

當JS端執(zhí)行window.webkit.messageHandlers.<方法名>.postMessage(<數(shù)據(jù)>).
此協(xié)議方法就會被執(zhí)行.,根據(jù)message.name判斷一下自己需要執(zhí)行哪步操作.message.body即是傳輸?shù)膮?shù)信息.(HTML中JS傳遞的數(shù)據(jù))

WKWebView 內(nèi)存泄露

但是這樣WebView所在的ViewController的- (void)dealloc{}不執(zhí)行.那么內(nèi)存又有問提了.
可以另外創(chuàng)建一個代理對象,然后通過代理對象回調(diào)指定的self.

//.h
@interface WeakScriptMessageDelegate : NSObject<WKScriptMessageHandler>

@property (nonatomic, assign) id<WKScriptMessageHandler> scriptDelegate;

- (instancetype)initWithDelegate:(id<WKScriptMessageHandler>)scriptDelegate;

@end


//.m
@implementation WeakScriptMessageDelegate

- (instancetype)initWithDelegate:(id<WKScriptMessageHandler>)scriptDelegate {
    self = [super init];
    if (self) {
        _scriptDelegate = scriptDelegate;
    }
    return self;
}

- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
    [self.scriptDelegate userContentController:userContentController didReceiveScriptMessage:message];
}

@end

設置代理

[[_webView configuration].userContentController addScriptMessageHandler:[[WeakScriptMessageDelegate alloc] initWithDelegate:self] name:@"方法名"];

WebView的ViewController的- (void)dealloc{}方法中進行銷毀.

- (void)dealloc {
    ...
    [[_webView configuration].userContentController removeScriptMessageHandlerForName:@"方法名"];
    ...
}

----------END

當然,安卓開發(fā)的盆友也是可以通過這種方式從中獲取網(wǎng)頁的數(shù)據(jù)的.安卓注入的接口名稱在JS中也是會報錯的.因此也需要try-catch.

好了.以上就是與大家分享的OC與JS交互(WebView監(jiān)聽事件).有不足之處還請各位大佬指出.萬分感激~

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末外邓,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子尉姨,更是在濱河造成了極大的恐慌,老刑警劉巖织咧,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件垃它,死亡現(xiàn)場離奇詭異迁霎,居然都是意外死亡,警方通過查閱死者的電腦和手機俺陋,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進店門豁延,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人腊状,你說我怎么就攤上這事诱咏。” “怎么了缴挖?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵袋狞,是天一觀的道長。 經(jīng)常有香客問我映屋,道長苟鸯,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任棚点,我火速辦了婚禮早处,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘瘫析。我一直安慰自己砌梆,他們只是感情好默责,可當我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著么库,像睡著了一般傻丝。 火紅的嫁衣襯著肌膚如雪甘有。 梳的紋絲不亂的頭發(fā)上诉儒,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天,我揣著相機與錄音亏掀,去河邊找鬼忱反。 笑死,一個胖子當著我的面吹牛滤愕,可吹牛的內(nèi)容都是我干的温算。 我是一名探鬼主播,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼间影,長吁一口氣:“原來是場噩夢啊……” “哼注竿!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起魂贬,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤巩割,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后付燥,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體宣谈,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年键科,在試婚紗的時候發(fā)現(xiàn)自己被綠了闻丑。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡勋颖,死狀恐怖嗦嗡,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情饭玲,我是刑警寧澤侥祭,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站咱枉,受9級特大地震影響卑硫,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜蚕断,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一欢伏、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧亿乳,春花似錦硝拧、人聲如沸径筏。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽滋恬。三九已至,卻和暖如春抱究,著一層夾襖步出監(jiān)牢的瞬間恢氯,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工鼓寺, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留勋拟,地道東北人。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓妈候,卻偏偏與公主長得像敢靡,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子苦银,可洞房花燭夜當晚...
    茶點故事閱讀 44,713評論 2 354

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

  • 前言 關于UIWebView的介紹,相信看過上文的小伙伴們所计,已經(jīng)大概清楚了吧柠辞,如果有問題,歡迎提問主胧。 本文是本系列...
    Dark_Angel閱讀 28,872評論 67 291
  • 隨著H5技術的興起叭首,在iOS開發(fā)過程中,難免會遇到原生應用需要和H5頁面交互的問題踪栋。其中會涉及方法調(diào)用及參數(shù)傳值等...
    Chris_js閱讀 3,068評論 1 8
  • 前言 關于UIWebView的介紹焙格,相信看過上文的小伙伴們,已經(jīng)大概清楚了吧夷都,如果有問題眷唉,歡迎提問。 本文是本系列...
    CoderLF閱讀 8,965評論 2 12
  • 最近整理了一下原生與H5之間的交互方式囤官,簡單的做個總結(jié)冬阳。OC端與JS的交互,大致有這幾種:攔截協(xié)議党饮、JavaScr...
    談Xx閱讀 31,122評論 41 75
  • 前言 上一篇專門講解了WKWebView相關的所有類肝陪、代理的所有API。前篇文章地址:http://blog.cs...
    iwolfox閱讀 1,105評論 1 1