iOS原生與H5交互

需求說明

目前的APP客戶端內(nèi),經(jīng)常需要嵌入H5頁面進(jìn)行混合開發(fā)。這樣,在開發(fā)過程中就會涉及到原生客戶端和H5交互的問題,本文就是簡單介紹一下iOS客戶端與H5頁面交互的一些方案,希望能解決大家的一些問題。

參考Demo:https://github.com/happyer-lwl/APP_Bridge_H5

一、Github上比較流行的是使用WebViewJavascriptBridge來實現(xiàn)交互

參考https://github.com/marcuswestin/WebViewJavascriptBridge

通過使用該庫可以輕松實現(xiàn)JS與原生交互。

// 初始化WebViewJavascriptBridge方法_bridge= [WebViewJavascriptBridge bridgeForWebView:self.webView webViewDelegate:selfhandler:^(iddata,WVJBResponseCallback responseCallback) {}];//原生與JS約定接口名為“testObjcCallback”,data是JS傳遞過來的信息,responseCallback來將信息傳遞給JS[_bridge registerHandler:@"testObjcCallback"handler:^(iddata,WVJBResponseCallback responseCallback) {? ? responseCallback("postInfomationToJS")}];

二、減少第三方依賴,使用iOS原生方法進(jìn)行交互處理

1、OC調(diào)用JS

可以通過webView直接調(diào)用JS的方法或者獲取JS屬性

NSString*title = [self.webView stringByEvaluatingJavaScriptFromString:@"document.title"];

OC還可以通過webView的上下文,并執(zhí)行JS腳本,為H5頁面動態(tài)添加方法和屬性,如下面代碼

// 獲取webView的上下文環(huán)境self.context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];// 為H5頁面動態(tài)添加屬性,并傳入APP端版本,之后H5可以使用此屬性[self.context evaluateScript:[NSStringstringWithFormat:@"var appVersion = %@",@"1.0.0"]];// 為H5頁面動態(tài)添加方法,并可以執(zhí)行[self.context evaluateScript:@"var triple = function(value) { return value * 3 }"];JSValue *tripleNum = [context evaluateScript:@"triple(num)"];

OC調(diào)用JS方法

// 獲取webView的上下文環(huán)境self.context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];NSString* method =@"returnLogin";? ? JSValue * function = [self.context objectForKeyedSubscript:method];//這里面的a,b,c就是OC調(diào)用JS的時候給JS傳的參數(shù)[function callWithArguments:@[@"hahahahahahahahah"]];

2、JS調(diào)用OC方法,可以有返回值,分兩種情況:

①js直接調(diào)用方法,比較簡單

②js通過對象調(diào)用方法,需要用到JSExport進(jìn)行一個綁定

一個協(xié)議如果遵從了JSExport協(xié)議,這個協(xié)議所規(guī)定的方法、變量等就會對js開放,我們可以通過js調(diào)用到

如果js是一個參數(shù)或者沒有參數(shù)的話 就比較簡單,我們的方法名和js的方法名保持一致即可

#import<UIKit/UIKit.h>#import<JavaScriptCore/JavaScriptCore.h>@protocolTestJSExport// callAppFunctionForJS 作為js方法的別名,可以相同JSExportAs (callAppFunction, - (void)callAppFunctionForJS:(NSString*)param);@end@interfaceViewController:UIViewController@property(weak,nonatomic)UIWebView*webView;@property(strong,nonatomic) JSContext *context;@end

#pragma mark - UIWebViewDelegate- (void)webViewDidFinishLoad:(UIWebView*)webView{// 以 html title 設(shè)置 導(dǎo)航欄 titleself.title = [webView stringByEvaluatingJavaScriptFromString:@"document.title"];// 取得webView的運行上下文self.context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];// 打印異常self.context.exceptionHandler =? ? ^(JSContext *context, JSValue *exceptionValue)? ? {? ? ? ? context.exception = exceptionValue;NSLog(@"%@", exceptionValue);? ? };// 以JSExport協(xié)議關(guān)聯(lián)native的方法,JS通過對象調(diào)用native的方法需要加入此關(guān)鍵詞,如native.callAppFunctionForJS('param');self.context[@"native"] =self;// js調(diào)用iOS? // 第一種方案// 其中showAlert就是js的方法名稱,block 里面是OC代碼? // 此方法最終將打印出所有接收到的參數(shù),js參數(shù)是不固定的 我們測試一下就知道? context[@"showAlert"] = ^() {NSArray*args = [JSContext currentArguments];for(idobjinargs) {NSLog(@"%@",obj);? ? ? ? ? }? ? ? }; }// js調(diào)用iOS? // 第二種方案// JS通過對象調(diào)用OC的方法// 可以有返回值給到JS- (NSString*)callAppFunctionForJS:(NSString*)param{NSLog(@"%@", param);}

2、小技術(shù)點

點擊導(dǎo)航欄返回,判斷APP原生返回還是H5頁面內(nèi)部返回

/**

返回判斷,確認(rèn)是否H5內(nèi)部跳轉(zhuǎn)了

@param sender

*/- (void)backAction:(id)sender{// 獲取webView當(dāng)前加載的頁面的數(shù)量,可以判斷是否在首頁,解決無法返回的問題NSString*webPageLength = [self.webView stringByEvaluatingJavaScriptFromString:@"history.length"];if([self.webView canGoBack] && (webPageLength.integerValue !=2)) {? ? ? ? [self.webView goBack];? ? }else{? ? ? ? [self.view resignFirstResponder];? ? ? ? [self.navigationController popViewControllerAnimated:YES];? ? }}

嵌入的H5頁面刷新或者跳轉(zhuǎn)之后,APP與H5的交互失效

原因

H5頁面刷新或者跳轉(zhuǎn)過后,原先的JSConext注入會消失,需要重新進(jìn)行注入

解決

在-(void)webViewDidFinishLoad:(UIWebView *)webView中重新進(jìn)行注入,切記:注入方法中的webView參數(shù)要用這個方法中帶的,不可使用自己類的webView屬性

- (void)webViewDidFinishLoad:(UIWebView*)webView{// webView不可用self.webView,要使用頁面刷新或者跳轉(zhuǎn)加載完成后的webViewself.context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 需求說明 目前的APP客戶端內(nèi),經(jīng)常需要嵌入H5頁面進(jìn)行混合開發(fā)。這樣,在開發(fā)過程中就會涉及到原生客戶端和H5交互...
    奔跑吧小二閱讀 2,592評論 1 50
  • 跟原生開發(fā)相比,H5的開發(fā)相對來一個成熟的框架和團(tuán)隊來講在開發(fā)速度和開發(fā)效率上有著比原生很大的優(yōu)勢,至少不用等待審...
    大沖哥閱讀 1,903評論 0 7
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對...
    cosWriter閱讀 11,658評論 1 32
  • 封裝的工具類: 工具的調(diào)用:
    dequal閱讀 1,321評論 2 0
  • https://www.cnblogs.com/ruixin-jia/p/6064948.html
    xmb閱讀 238評論 0 0

友情鏈接更多精彩內(nèi)容