需求: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('你你好我叫鄭伊健');
}