iOS与js交互(WebView+WKWebView)

心已入冬 提交于 2019-12-08 19:40:45

 

需求: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.webviewvalueForKeyPath:@"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传值"οnclick="obj.call()">

 

//oc给js传值:js点击按钮获取oc中的值---也就是点击js端触发call事件时调用occall方法我们可以在理做原生的push pop等

-(void)call{

    

    // 调用js中的Call1方法

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

    //传值给web端call1函数字符串

    [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端只要在需要在触发需要传值得函数中加入以下方法

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

 

其中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端需要调用的方法 name是js端的方法名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 =@"OC给js端传过去的测试值--随便写吧我爱鹿晗";

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

    //OC调用JS中

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

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

    }];

    

}

 

js端代码

<button οnclick="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传值"οnclick="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('你你好我叫郑伊健');

}

 

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!