ios端與js交互(WebView+WKWebView)

需求:1點(diǎn)擊js登入按鈕將用戶賬號(hào)和密碼傳給移動(dòng)端
2將地東段的token傳給html端

ios端
有3種方法
1:webview的javascriptCore
2:webkit
3:uir攔截
4:第三方庫

理論:js與oc相互調(diào)用并且傳值 我們可以理解成河2邊需要送東西的過程 我們需要在js和oc之間搭建一個(gè)橋梁而jsexport就是這做橋梁,有了橋梁以后在2端傳值我們還需要一個(gè)對(duì)象(快遞員)
就好比現(xiàn)實(shí)中js在橋的一段,而移動(dòng)端在橋的這一邊現(xiàn)在他們需要給彼此送東西那么就需要一個(gè)快遞員(對(duì)象)理解了吧,哈哈。好了現(xiàn)在我們來舉個(gè)例子

第一種方法jscascriptcore
第一步搭建2端之間橋梁javascriptcore

1)導(dǎo)入javascriptCore
Build phass->link binary with libraries
添加頭文件

import<JavaScriptCore/JavaScriptCore.h>

2)初始化橋梁
@property(nonatomic,strong)JSContext *jsContext;
在web的webViewDidFinishLoad:代理方法中
self.jsContext = [self.webview valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
讓js中的快遞員搬運(yùn)工也讓oc所持有
self.jsContext[@"objcet"] = self;

self.jsContext.exceptionHandler = ^(JSContext *context, JSValue *exception) {
    context.exception = exception;
    NSLog(@"錯(cuò)誤信息:%@",exception);
};

3創(chuàng)建快遞員其中object就是js端的對(duì)象 一般是js端創(chuàng)建好的我們移動(dòng)端只要引用這個(gè)快遞員
self.jsContext[@"objcet"] = self;
好了現(xiàn)在橋梁有了搬運(yùn)工也有了現(xiàn)在我們需要給搬運(yùn)工一個(gè)交通工具(代理方法)

4)創(chuàng)建對(duì)象傳遞工具—摩托車(代理方法) 注意:交通工具是js端定義的,一般都是協(xié)商好的 下面的getcall就是快遞員需要搭乘的交通工具而callstring這個(gè)字符串就是快遞
@protocol JSObjcDelegate <JSExport>

  • (void)getcall:(NSString *)callString;
    @end

5)oc端接收快遞不對(duì),接收值
-(void)getcall:(NSString *)callstring{
}
好了,js端可以給oc傳值了 完成了

二:oc給js傳值

js端定義個(gè)點(diǎn)擊事件 call()并且該點(diǎn)擊事件被obj對(duì)象(這個(gè)對(duì)象就是oc對(duì)象)持有當(dāng)觸發(fā)call事件時(shí)會(huì)調(diào)用oc端的call方法
我們這這里可以給js端傳值
<input type="button" value="js端接收oc傳值" onclick="obj.call()">

//oc給js傳值:js點(diǎn)擊按鈕獲取oc中的值---也就是點(diǎn)擊js端觸發(fā)call事件時(shí)調(diào)用occall方法 我們可以在理做原生的push pop等
-(void)call{

// 調(diào)用js中的Call1方法
JSValue *Callback = self.jsContext[@"Call1"];
//傳值給web端call1函數(shù)字符串
[Callback callWithArguments:@[@"我是oc端傳給js端的值測(cè)試值:123456789"]];

}
js端call1函數(shù)方法
var Call1 = function(str)
{
alert(str);
}

————————————————WKWebView中js交互
WKWebview
和webview差不多只不過我們的橋梁變成了
WKUserContentController *conntentController
這家伙可以充當(dāng)我們的橋梁作用
而且它有一個(gè)方法可以讓我oc端直接監(jiān)聽到j(luò)s端的某一個(gè)快遞員 其中第一個(gè)參數(shù)是代理,name:就是js端的快遞員名字
[conntentController addScriptMessageHandler:self name:@"getUserandPwd"];
js端只要在需要傳值得函數(shù)中加入以下函數(shù)
其中g(shù)etUseranPwd就是需要監(jiān)聽的快遞員名字,而postMessage()中是需要傳送的值
window.webkit.messageHandlers.getUserandPwd.postMessage(xxxx)

當(dāng)我們js端的方法被觸發(fā)而里面的快遞員將會(huì)被派送出去oc端也監(jiān)聽到了快遞員來了接下來就需要簽收快遞
我們?cè)谙旅孢@個(gè)方法中來接收快遞
其中第一個(gè)參數(shù)是初始化wkweb時(shí)的配置信息可以打印一下,而后面的message就是消息體(快遞單里面有快遞員名字,電話和快遞)其中
message.name—>快遞員名字
message.body——>快遞(js端傳來的值)
如果js端創(chuàng)建了多個(gè)快遞員那么我們需要根據(jù)名字來分別接受快遞(處理)
注意:這個(gè)方法是關(guān)鍵我們相互傳至的關(guān)鍵
-(void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{

oc給js傳值
例子:oc無法直接給js端觸發(fā)事件的函數(shù)傳智,只能當(dāng)js端點(diǎn)擊了某一個(gè)按鈕給oc端派送一個(gè)空的快遞 我們oc端監(jiān)聽到了然后傳智給js端(調(diào)用js端的函數(shù))
[self.web evaluateJavaScript:Call1Result completionHandler:^(id _Nullable result, NSError * _Nullable error) {
NSLog(@"111%@", error);
}];
其中:第一個(gè)函數(shù)是函數(shù)名字 block中顯示調(diào)用結(jié)果
下面的列子其中Call(str)就是js端的某一個(gè)函數(shù)而str是值
NSString *Call1Result = [NSString stringWithFormat:@"Call1('%@')",str];

完整代碼
初始化web
WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc]init];
WKUserContentController *conntentController = [[WKUserContentController alloc]init];

//獲取js端需要調(diào)用的方法 name是js端的方法名getUserandPwd (message.Body>消息體)

// window.webkit.messageHandlers.getUserandPwd.postMessage(<message.Body>)
//這個(gè)是監(jiān)聽js端點(diǎn)擊事件當(dāng)js端觸在這2個(gè)事件中添加了上面的方法那么這2個(gè)點(diǎn)擊事件那么我們oc端就可以知道并且做出回應(yīng)
[conntentController addScriptMessageHandler:self name:@"getUserandPwd"];
[conntentController addScriptMessageHandler:self name:@"CallGet"];

config.userContentController = conntentController;

self.web = [[WKWebView alloc]initWithFrame:self.view.bounds configuration:config];

self.web.UIDelegate = self;
[self.view addSubview:self.web];

在web的這個(gè)delegate方法 不然會(huì)報(bào)錯(cuò)

  • (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler{

    NSLog(@"%@",message);

    //必須要加上這句不然不執(zhí)行
    completionHandler();

}

監(jiān)聽
-(void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{

// //oc代碼傳給js端
if ([message.name isEqualToString:@"CallGet"]) {

    [self shareJS];
    //js傳值給oc
} else if ([message.name isEqualToString:@"getUserandPwd"]){
    //接收js端傳值
    NSString *UserStr = [NSString stringWithFormat:@"%@",message.body[@"user"]];
    NSString *PassWordStr = [NSString stringWithFormat:@"%@",message.body[@"password"]];
    
    NSLog(@"我是js端傳過來的值:用戶名%@ 密碼:%@",UserStr,PassWordStr);

}

}

-(void)shareJS{

NSString *str = @"OC給js端傳過去的測(cè)試值--隨便寫吧我愛鹿晗";
NSString *Call1Result = [NSString stringWithFormat:@"Call1('%@')",str];
//OC調(diào)用JS
[self.web evaluateJavaScript:Call1Result completionHandler:^(id _Nullable result, NSError * _Nullable error) {
    NSLog(@"111%@", error);
}];

}

js端代碼
<button onclick="copyText()">登入-傳值給client</button>

function copyText() {

  <!--wkweb使用-->
  window.webkit.messageHandlers.getUserandPwd.postMessage({user:document.getElementById("user").value,password:document.getElementById("password").value});


    <!--webvieiw使用其中object就是對(duì)象(快遞員)getcall(NSStirng *)-->


}

<input type="button" value="js端接收oc傳值" onclick="call()">
</div>

<h1>回調(diào)展示區(qū)</h1>
<textarea id ="returnValue" type="value" rows="5" cols="40">


function Call1(str)
{
document.getElementById("returnValue").value = str;

}
function call() {
window.webkit.messageHandlers.CallGet.postMessage(null);
alert('你你好我叫鄭伊健');
}

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

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

  • 跟原生開發(fā)相比,H5的開發(fā)相對(duì)來一個(gè)成熟的框架和團(tuán)隊(duì)來講在開發(fā)速度和開發(fā)效率上有著比原生很大的優(yōu)勢(shì),至少不用等待審...
    大沖哥閱讀 1,902評(píng)論 0 7
  • 前言 Web 頁面中的 JS 與 iOS Native 如何交互是每個(gè) iOS 猿必須掌握的技能。而說到 Nati...
    幽城88閱讀 2,328評(píng)論 1 8
  • 最近在做的項(xiàng)目重點(diǎn)就是原生app與js的交互,以前也做過但是并沒有深入的了解和研究過,因?yàn)檫@個(gè)項(xiàng)目我嘗試了三種方式...
    Www劉閱讀 14,353評(píng)論 3 53
  • 我不過是旅人,在這陌生的城市飄蕩,迷茫而又充滿希望,想著有一天,飄啊飄啊,飄到了夢(mèng)想的地方。國(guó)美,加油!
    筆歌墨舞閱讀 133評(píng)論 0 1
  • 門面房,店高兩米八。粉紅色墻壁,玻璃柜,呈列著奶粉,煙酒。白色的貨架,擺滿了品種繁多的商品。位于交通要道,三岔路口...
    玉妮閱讀 406評(píng)論 12 6

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