1. 程式人生 > >iOS與js互動(WebView+WKWebView)

iOS與js互動(WebView+WKWebView)

需求:1點選js登入按鈕將使用者賬號和密碼傳給移動端

            2將客戶端的token傳給html端

據我瞭解有以下幾種方法

1:webview的javascriptCore

2:webkit

3:url攔截

4:第三方庫

我用的是1和2

理論:js與oc相互呼叫並且傳值 我們可以理解成河2邊需要送東西的過程 我們需要在js和oc之間搭建一個橋樑而jsexport就是這做橋樑,有了橋樑以後在2端傳值我們還需要一個物件(快遞員)

就好比現實中js在橋的一段,而移動端在橋的這一邊現在他們需要給彼此送東西那麼就需要一個快遞員(物件)

----------------------------------------------------------

第一種WebView+javascriptCore

第一步搭建2端之間橋樑javascriptcore

1)匯入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中的快遞員搬運工也讓oc所持有

    self.jsContext[@"objcet"] =self;

    self.jsContext.exceptionHandler = ^(JSContext *context,JSValue *exception) {

        context.exception = exception;

        NSLog(@"錯誤資訊:%@",exception);

    };

3建立快遞員其中object就是js端的物件 一般是js端建立好的我們移動端只要引用這個快遞員

self.jsContext[@"objcet"] =self;

好了現在橋樑有了搬運工也有了現在我們需要給搬運工一個交通工具(代理方法)

4)建立物件傳遞工具—摩托車(代理方法)  注意:交通工具是js端定義的,一般都是協商好的 下面的getcall就是快遞員需要搭乘的交通工具而callstring這個字串就是快遞

@protocol JSObjcDelegate <JSExport>

- (void)getcall:(NSString *)callString;

@end

5)oc端接收快遞不對,接收值

-(void)getcall:(NSString *)callstring{

}

好了,js端可以給oc傳值了 完成了

二:oc給js傳值

js端定義個點選事件 call()並且該點選事件被obj物件(這個物件就是oc物件)持有當觸發call事件時會呼叫oc端的call方法

我們這這裡可以給js端傳值

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

//ocjs傳值:js點選按鈕獲取oc中的值---也就是點選js端觸發call事件時呼叫occall方法我們可以在理做原生的push pop

-(void)call{

// 呼叫js中的Call1方法

    JSValue *Callback = self.jsContext[@"Call1"];

//傳值給webcall1函式字串

    [Callback callWithArguments:@[@"我是oc端傳給js端的值測試值:123456789"]];

}

js端call1函式方法

var Call1 = function(str)

{

    alert(str);

}

---------------------------------------------------------

第二種方法:WKWebView中與js互動

和webview差不多隻不過我們的橋樑變成了

WKUserContentController *conntentController

這傢伙可以充當我們的橋樑作用

而且它有一個方法可以讓我oc端直接監聽到js端的某一個快遞員 其中第一個引數是代理,name:就是js端的快遞員名字

   [conntentController addScriptMessageHandler:selfname:@"getUserandPwd"];

js端只要在需要在觸發需要傳值得函式中加入以下方法

window.webkit.messageHandlers.getUserandPwd.postMessage(xxxx);

其中getUseranPwd就是需要監聽的快遞員名字,postMessage()中是需要傳送的值

當我們js端的方法被觸發而裡面的快遞員將會被派送出去oc端也監聽到了快遞員來了接下來就需要簽收快遞

我們在下面這個方法中來接收快遞

其中第一個引數是初始化wkweb時的配置資訊可以列印一下,而後面的message就是訊息體(快遞單裡面有快遞員名字,電話和快遞)其中

message.name—>快遞員名字

message.body——>快遞(js端傳來的值)

如果js端建立了多個快遞員那麼我們需要根據名字來分別接受快遞(處理)

注意:這個方法是關鍵我們相互傳至的關鍵

-(void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{

oc給js傳值

例子:oc無法直接給js端觸發事件的函式傳智,只能當js端點選了某一個按鈕給oc端派送一個空的快遞 我們oc端監聽到了然後傳智給js端(呼叫js端的函式)

 [self.webevaluateJavaScript:Call1Result completionHandler:^(id_Nullable result,NSError * _Nullable error) {

        NSLog(@"111%@", error);

    }];

其中:第一個函式是函式名字  block中顯示呼叫結果

下面的列子其中Call(str)就是js端的某一個函式而str是值

NSString *Call1Result = [NSStringstringWithFormat:@"Call1('%@')",str];

部分關鍵程式碼

初始化web

WKWebViewConfiguration *config = [[WKWebViewConfigurationalloc]init];

WKUserContentController *conntentController = [[WKUserContentControlleralloc]init];

//獲取js端需要呼叫的方法 namejs端的方法名getUserandPwd (message.Body>訊息體)

//   window.webkit.messageHandlers.getUserandPwd.postMessage(<message.Body>)

//這個是監聽js端點選事件當js端觸在這2個事件中添加了上面的方法那麼這2個點選事件那麼我們oc端就可以知道並且做出迴應

    [conntentController addScriptMessageHandler:selfname:@"getUserandPwd"];

    [conntentController addScriptMessageHandler:selfname:@"CallGet"];

    config.userContentController = conntentController;

self.web = [[WKWebViewalloc]initWithFrame:self.view.boundsconfiguration:config];

self.web.UIDelegate =self;

    [self.viewaddSubview:self.web];

在web的這個delegate方法 不然會報錯

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

    NSLog(@"%@",message);

//必須要加上這句不然不執行

   completionHandler();

}

監聽

-(void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{

//    //oc程式碼傳給js

    if ([message.nameisEqualToString:@"CallGet"]) {

        [self shareJS];

//js傳值給oc

    } else if ([message.nameisEqualToString:@"getUserandPwd"]){

//接收js端傳值

NSString *UserStr = [NSStringstringWithFormat:@"%@",message.body[@"user"]];

        NSString *PassWordStr = [NSStringstringWithFormat:@"%@",message.body[@"password"]];

        NSLog(@"我是js端傳過來的值:使用者名稱%@密碼:%@",UserStr,PassWordStr);

    }

}

-(void)shareJS{

NSString *str =@"OCjs端傳過去的測試值--隨便寫吧我愛鹿晗";

NSString *Call1Result = [NSStringstringWithFormat:@"Call1('%@')",str];

//OC呼叫JS中

    [self.webevaluateJavaScript: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就是物件(快遞員)getcall(NSStirng *)-->

<!--        obj.getcall(document.getElementById("user").value+document.getElementById("password").value);-->

        }

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

</div>

<h1>回撥展示區</h1>

<textarea id ="returnValue"type="value"rows="5"cols="40">

<!--webview使用oc端呼叫js端的方法並且傳給js端值-->

function Call1(str)

{

     document.getElementById("returnValue").value = str;

<!--    alert(str);-->

}

function call() {

    window.webkit.messageHandlers.CallGet.postMessage(null);

    alert('你你好我叫鄭伊健');

}