美文网首页
iOS与js交互

iOS与js交互

作者: 代江波 | 来源:发表于2019-03-07 16:04 被阅读0次

    1.UIWebview的js交互

    iOS7之后苹果推出了JavaScriptCore这个框架,从而让web页面和本地原生应用交互起来非常方便,而且使用此框架可以做到Android那边和iOS相对统一,web前端写一套代码就可以适配客户端的两个平台,从而减少了web前端的工作量。

    JavaScriptCore有如下几个类
    #import "JSContext.h"
    #import "JSValue.h"
    #import "JSManagedValue.h"
    #import "JSVirtualMachine.h"
    #import "JSExport.h"
    
    1>JSContext代表一个JavaScript的执行环境的一个实例。

    创建方法

    JSContext *context = [self.myWebView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
    
    2>JSValue的主要作用就是用来接收JSContext执行后的返回结果
    <script type="text/javascript">
          var myObject = "myObject";
      </script>
    JSValue *myObject = self.context[@"myObject"]; 
    NSLog(@"%@",[myObject toString]);
    
    3>JSManagedValue JS和OC对象的内存管理辅助对象。由于JS内存管理是垃圾回收,并且JS中的对象都是强引用,而OC是引用计数。如果双方相互引用,势必会造成循环引用,而导致内存泄露。我们可以用JSManagedValue保存JSValue来避免。
    4>JSVirtualMachine JS运行的虚拟机,有独立的堆空间和垃圾回收机制。
    5>JSExport 一个协议,如果JS对象想直接调用OC对象里面的方法和属性,那么这个OC对象只要实现这个JSExport协议就可以了。

    iOS调用js方法

    #pragma mark  js代码
    // 有参数
    function numAddMethod(num1,num2){
        alert(num1 + num2);
        return num1 + num2;
    }
    // 无参数
    function numAddMethod2(){
        alert('调用numAddMethod2');
    }
    #pragma mark  iOS方法
    - (void)iOSMethod{
         //创建上下文
        JSContext *context = [self.myWebView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
        //调用有参数的js方法
        JSValue *value = [context[@"numAddMethod"] callWithArguments:@[@(5),@(6)]];
        //调用无参数的js方法
        JSValue *value2 = [context[@"numAddMethod2"] callWithArguments:@[]];
    
        NSLog(@"有参数返回值=%d === 无参数返回值",value.toInt32,value2.toInt32);
         //打印结果,有参数返回值=11===无参数返回值0
    }
    

    js调用iOS方法

    #pragma mark  js代码
    <head>
        <script type = "text/javascript">
             function viewClicked(){
                 share('1','2','3');
             }
         </script>
    </head>
    <body>
         <button type="button" onclick="viewClicked()">Click Me!</button>
    </body>
    #pragma mark  iOS代码
    -(void)viewDidLoad{
        [super viewDidLoad];
        JSContext *context = [self.myWebView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
        context[@"share"] = ^(){
            NSArray *args = [JSContext currentArguments];
            for (JSValue *jsValue in args) {
                NSLog(@"%@",jsValue.toString);
            }
        };
        //arguments保存js传入的参数,打印结果为1,2,3.
    }
    

    WKWebView的js交互

    首先来一段代码,来创建一个WKWebView

    
    @interface WKWebViewController ()<WKUIDelegate,WKNavigationDelegate,WKScriptMessageHandler>
        
    @property (nonatomic, strong) WKWebView *webView;
    
    @property (nonatomic, strong) WKUserContentController *userContent;
    
    @end
    
    @implementation WKWebViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        self.view.backgroundColor = [UIColor whiteColor];
        
        WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
        self.userContent = [[WKUserContentController alloc] init];
       
        [self.userContent addScriptMessageHandler:self name:@"ocMethod"];
        
        config.userContentController = self.userContent;
        self.webView = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:config];
        
        self.webView.UIDelegate = self;
        self.webView.navigationDelegate = self;
        [self.view addSubview:self.webView];
        
        NSURL *url = [[NSBundle mainBundle] URLForResource:@"index" withExtension:@"html"];
        NSURLRequest *request = [NSURLRequest requestWithURL:url];
        [self.webView loadRequest:request];
    }
        
    

    特别关注WKUserContentController的addScriptMessageHandler:name:方法

    
    /*! @abstract Adds a script message handler.
      //添加一个js要调用的方法
     @param scriptMessageHandler The message handler to add.
     //添加消息处理界面
     @param name The name of the message handler.
     //js要执行的方法名称
     @discussion Adding a scriptMessageHandler adds a function
     window.webkit.messageHandlers.<name>.postMessage(<messageBody>) for all
     frames.
      //需要js执行的方法规则
      //window.webkit.messageHandlers.<name>.postMessage(<messageBody>)
     */
    - (void)addScriptMessageHandler:(id <WKScriptMessageHandler>)scriptMessageHandler name:(NSString *)name;
    

    这个方法可能会引起内存泄漏,解决方法百度上有很多,这里不做说明。

    1>iOS原生方法调用js方法
    #pragram mark -- js代码
    function jsMethod(obj){
        return obj;
    }
    
    #pragram mark -- iOS代码
    - (void)iOSMethod{
        NSDictionary *dict = @{@"key1":@"value1",@"key2":@"value2"};
        NSData *dictData = [NSJSONSerialization dataWithJSONObject:dict options:NSJSONWritingPrettyPrinted error:nil];
        NSString *dictStr = [[NSString alloc] initWithData:dictData encoding:NSUTF8StringEncoding];
        NSString *jsStr = [NSString stringWithFormat:@"jsMethod(%@)",dictStr];
        [self.webView evaluateJavaScript:jsStr completionHandler:^(id _Nullable result, NSError * _Nullable error) {
            NSLog(@"return == %@",result);
        }];
        //iOS给js传入多个参数可以通过转成字符串的方法传给js
        //打印结果为@{@"key1":@"value1",@"key2":@"value2"},说明js方法返回值都在result里面
    }
        
    
    2>js调用iOS原生方法
    #pragram mark -- js代码
    <head>
        <script type = "text/javascript">
             function viewClicked(){
                 //固定写法,方法名为iOS原生要执行的方法(这里的方法名为ocMethod,上面已经注册过),参数放在()中
                 window.webkit.messageHandlers.ocMethod.postMessage({'key':'value'});
             }
         </script>
    </head>
    <body>
         <button type="button" onclick="viewClicked()">Click Me!</button>
    </body>
    
    #pragram mark -- iOS代码
    #pragram mark -- WKScriptMessageHandler
    - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{
        NSString *messageName = message.name;
        if ([@"ocMethod" isEqualToString:messageName]) {
            id messageBody = message.body;
            NSLog(@"%@",messageBody);
            //当js调用ocMethod时,就可以来到这里,然后就可以在这里写iOS原生代码了,js所传的参数都在message.body里面了
        }
    }
    
    

    UIWebView和WKWebView与js交互的方法不能通用,项目在换webView时,会造成一点的麻烦。

    使用WebViewJavascriptBridge可以适配两种webView

    相关文章

      网友评论

          本文标题:iOS与js交互

          本文链接:https://www.haomeiwen.com/subject/cdjcpqtx.html