iOS APP 與 h5交互

iOS與h5交互可以分為兩部分,一部分是UIWebView與h5交互,一部分是WKWebView與h5交互,

1.UIWebView與h5交互

h5內(nèi)URL攔截

可以在代理方法- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType;中攔截實(shí)現(xiàn)
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
  NSString * urlString = request.URL.absoluteString;
  NSString * scheme =  request.URL.scheme;
// 可以在此處根據(jù)url地址,或者 scheme判斷是否需要攔截,返回NO,則不會(huì)跳轉(zhuǎn)
return YES;
}

為H5添加js方法

在代理方法- (void)webViewDidFinishLoad:(UIWebView *)webView;加載完頁面之后插入js代碼,如給h5頁面所有的圖片添加點(diǎn)擊事件(ps:如果可能的話還是讓前段自己加吧~~)
- (void)webViewDidFinishLoad:(UIWebView *)webView {
//添加圖片可點(diǎn)擊JS
[webView stringByEvaluatingJavaScriptFromString:@"function registerImageClickAction(){\
   var imgs=document.getElementsByTagName('img');\
   var length=imgs.length;\
   for(var i=0;i<length;i++){\
     img=imgs[i];\
    img.onclick=function(){\
     window.location.href='image-preview:'+this.src}\
   }\
 }"];
}

重點(diǎn),原生與h5交互,即:原生調(diào)用h5方法,h5調(diào)用原生方法

首先配置環(huán)境,原生要繼承JSExport協(xié)議(ps:需要導(dǎo)入頭文件 <JavaScriptCore/JavaScriptCore.h>),并且添加協(xié)議方法提供給h5調(diào)用,如:
@protocol JSObjcDelegate <JSExport>
//不帶參數(shù)調(diào)用
- (void)call;
//帶參數(shù)調(diào)用
- (void)getCall:(NSString *)callString;
@end
然后在控制器中創(chuàng)建UIWebView并設(shè)置代理,實(shí)現(xiàn)剛剛聲明的協(xié)議 JSObjcDelegete,并設(shè)置一個(gè)全局的jsContext
@interface JKUIwebViewTestVC : UIViewController <UIWebViewDelegate, JSObjcDelegate>
@property (nonatomic, strong) JSContext *jsContext;
@property (strong, nonatomic)  UIWebView *webView;
@end
- (void)webViewDidFinishLoad:(UIWebView *)webView代理方法中設(shè)置jsContext,因?yàn)槿绻鹷ebView中有鏈接跳轉(zhuǎn),就必須要重新設(shè)置,否則h5無法調(diào)用原生方法,下方JKAPP是提供給h5調(diào)用的對(duì)象(PS:建議把所有的UI操作都放到主線程操作,否則的話有可能導(dǎo)致線程崩潰,是有可能~~~~)
self.jsContext = [self.webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
self.jsContext[@"JKAPP"] = self;
self.jsContext.exceptionHandler = ^(JSContext *context, JSValue *exceptionValue) {
      context.exception = exceptionValue;
      NSLog(@"異常信息:%@", exceptionValue);
};
最后實(shí)現(xiàn)JSObjcDelegete方法,就可以提供給h5調(diào)用了,原生可以用JSValue去調(diào)用h5方法,具體如下
- (void)call {
  dispatch_async(dispatch_get_main_queue(), ^{
        UIAlertController * alert = [UIAlertController alertControllerWithTitle:@"" message:@"\(^o^)/~h5調(diào)用原生成功" preferredStyle:(UIAlertControllerStyleAlert)];
      UIAlertAction * cancleAction = [UIAlertAction actionWithTitle:@"確定" style:(UIAlertActionStyleCancel) handler:nil];
   [alert addAction:cancleAction];
      [self presentViewController:alert animated:YES completion:nil];
   });
}

- (void)getCall:(NSString *)callString {
JSValue *Callback = self.jsContext[@"alerCallback"];
[Callback callWithArguments:@[@"原生去調(diào)用h5了"]];

}

h5可以這樣調(diào)用原生方法
<input type="button" value="h5喚起原生方法(call)" 
onclick="JKAPP.call()">
</div>
<div>
<input type="button" value="h5喚起原生方法getCall:(NSString 
*)callString傳值,并且原生調(diào)用h5方法" onclick="call()">
 </div>

遇到問題總結(jié)

1.在代理方法中操作UI偶爾導(dǎo)致線程崩潰
 解決方案:所有UI操作都放到主線程操作
2.jsContext對(duì)象注入失敗.
 原因:h5在頁面加載時(shí)需要獲取一些原生內(nèi)的信息,此時(shí)頁面尚未加載,jsContext對(duì)象尚未注入,獲取信息失敗,js代碼不在加載
 解決方案1.先是h5在頁面加載完成之后再去獲取jsContext對(duì)象獲取信息,但是嘗試失敗了,對(duì)象仍然沒有注入成功.然后h5在頁面加載完成時(shí)添加了一個(gè)短暫延時(shí),,然后再去獲取信息,成功解決問題.
 解決方案2.猜測(cè),未證實(shí)!!!我們h5中是先加載頁面,最后加載js,此時(shí)頁面加載完成,js不一定加載完成,有可能導(dǎo)致js對(duì)象注入失敗,猜測(cè),先加載js,在加載頁面,然后在頁面加載完成時(shí)去獲取對(duì)象加載信息,有可能能解決問題.

  1. JSValue *Callback = self.jsContext[@"alerCallback"];
    [Callback callWithArguments:@[@"原生去掉用h5了"]]; 
    

此方法有可能導(dǎo)致線程崩潰,而且頻率不低.
解決辦法:

dispatch_async(dispatch_get_main_queue(), ^{
                if (weakSelf.jsContext && data.length > 0) {
                    JSValue *Callback = weakSelf.jsContext[callBack];
                    [weakSelf.jsContext[@"setTimeout"] callWithArguments:@[Callback, @0, data]];
                }
            });

使用此方式去回調(diào)h5方法,暫未發(fā)現(xiàn)崩潰現(xiàn)象,注意

[weakSelf.jsContext[@"setTimeout"] callWithArguments:@[Callback, @0, data]]; 

其中以@0分割,前面是JSValue對(duì)象,后面是參數(shù),如果有多個(gè)參數(shù)可以使用數(shù)組

2.WKWebview與h5交互

h5內(nèi)URL攔截

可以在代理方法- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType;中攔截實(shí)現(xiàn)
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
NSURL * url = navigationAction.request.URL;
NSString * scheme = [url scheme];

decisionHandler(WKNavigationActionPolicyAllow);
//    decisionHandler(WKNavigationActionPolicyCancel);
}

需要注意的是,實(shí)現(xiàn)此方法必須要調(diào)用decisionHandler這個(gè)block否則會(huì)導(dǎo)致app崩潰,參數(shù)是枚舉類型,WKNavigationActionPolicyAllow代表允許加載,WKNavigationActionPolicyCancel代表不允許加載

原生調(diào)用h5方法,KWebView 提供了一個(gè)evaluateJavaScript:completionHandler:方法,可以在此方法中實(shí)現(xiàn)原生調(diào)用js.

- (void)getAlertCall {
    NSString *jsStr = [NSString 
    stringWithFormat:@"alerCallback('%@')",@"原生調(diào)用h5中的js成功"];
    [self.webView evaluateJavaScript:jsStr completionHandler:^(id _Nullable result, NSError * _Nullable error) {
        NSLog(@"%@----%@",result, error);
    }];
}

PS:一定要注意,在WKWebView中alert被攔截掉了,網(wǎng)頁不能直接彈出來要在代理方法- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler中自己實(shí)現(xiàn)彈窗,并且要調(diào)用completionHandler回調(diào),否則會(huì)導(dǎo)致程序崩潰

- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler {
NSLog(@"%@", message);

completionHandler();
}

h5調(diào)用原生方法,controller需要實(shí)現(xiàn)WKScriptMessageHandler代理,然后設(shè)置 [configuration.userContentController addScriptMessageHandler:self name:@"call"];其中name為方法名.然后原生在代理- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message中檢測(cè)js回調(diào),js可以這么調(diào)用window.webkit.messageHandlers.call.postMessage("h5調(diào)用原生!");,其中call是協(xié)商的方法名,postMessage為參數(shù)

- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
    NSLog(@"+++++%@++++%@", message.body, message.name);
}

詳細(xì)代碼Demo地址

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市囱挑,隨后出現(xiàn)的幾起案子殿衰,更是在濱河造成了極大的恐慌彻采,老刑警劉巖壤蚜,帶你破解...
    沈念sama閱讀 216,496評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡验庙,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門社牲,熙熙樓的掌柜王于貴愁眉苦臉地迎上來粪薛,“玉大人,你說我怎么就攤上這事搏恤∥ナ伲” “怎么了?”我有些...
    開封第一講書人閱讀 162,632評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵挑社,是天一觀的道長。 經(jīng)常有香客問我巡揍,道長痛阻,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,180評(píng)論 1 292
  • 正文 為了忘掉前任腮敌,我火速辦了婚禮阱当,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘糜工。我一直安慰自己弊添,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,198評(píng)論 6 388
  • 文/花漫 我一把揭開白布捌木。 她就那樣靜靜地躺著油坝,像睡著了一般。 火紅的嫁衣襯著肌膚如雪刨裆。 梳的紋絲不亂的頭發(fā)上澈圈,一...
    開封第一講書人閱讀 51,165評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音帆啃,去河邊找鬼瞬女。 笑死,一個(gè)胖子當(dāng)著我的面吹牛努潘,可吹牛的內(nèi)容都是我干的诽偷。 我是一名探鬼主播,決...
    沈念sama閱讀 40,052評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼疯坤,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼报慕!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起压怠,我...
    開封第一講書人閱讀 38,910評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤卖子,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后刑峡,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體洋闽,經(jīng)...
    沈念sama閱讀 45,324評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡玄柠,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,542評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了诫舅。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片羽利。...
    茶點(diǎn)故事閱讀 39,711評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖刊懈,靈堂內(nèi)的尸體忽然破棺而出这弧,到底是詐尸還是另有隱情,我是刑警寧澤虚汛,帶...
    沈念sama閱讀 35,424評(píng)論 5 343
  • 正文 年R本政府宣布匾浪,位于F島的核電站,受9級(jí)特大地震影響卷哩,放射性物質(zhì)發(fā)生泄漏蛋辈。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,017評(píng)論 3 326
  • 文/蒙蒙 一将谊、第九天 我趴在偏房一處隱蔽的房頂上張望冷溶。 院中可真熱鬧,春花似錦尊浓、人聲如沸逞频。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽苗胀。三九已至,卻和暖如春瓦堵,著一層夾襖步出監(jiān)牢的瞬間柒巫,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評(píng)論 1 269
  • 我被黑心中介騙來泰國打工谷丸, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留堡掏,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,722評(píng)論 2 368
  • 正文 我出身青樓刨疼,卻偏偏與公主長得像泉唁,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子揩慕,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,611評(píng)論 2 353

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

  • 1.ios高性能編程 (1).內(nèi)層 最小的內(nèi)層平均值和峰值(2).耗電量 高效的算法和數(shù)據(jù)結(jié)構(gòu)(3).初始化時(shí)...
    歐辰_OSR閱讀 29,372評(píng)論 8 265
  • 跟原生開發(fā)相比亭畜,H5的開發(fā)相對(duì)來一個(gè)成熟的框架和團(tuán)隊(duì)來講在開發(fā)速度和開發(fā)效率上有著比原生很大的優(yōu)勢(shì),至少不用等待審...
    大沖哥閱讀 1,845評(píng)論 0 7
  • 隨著H5技術(shù)的興起迎卤,在iOS開發(fā)過程中拴鸵,難免會(huì)遇到原生應(yīng)用需要和H5頁面交互的問題。其中會(huì)涉及方法調(diào)用及參數(shù)傳值等...
    Chris_js閱讀 3,068評(píng)論 1 8
  • 前言 Web 頁面中的 JS 與 iOS Native 如何交互是每個(gè) iOS 猿必須掌握的技能。而說到 Nati...
    幽城88閱讀 2,204評(píng)論 1 8
  • 最近出現(xiàn)寫作敷衍劲藐、拖延的情況八堡,開始出現(xiàn)熱情褪去的征兆,剛好學(xué)習(xí)到“為什么你總是半途而廢”這篇文章聘芜,及時(shí)調(diào)用元認(rèn)知進(jìn)...
    官小波閱讀 128評(píng)論 1 0