美文网首页程序员
webview与js交互

webview与js交互

作者: 鄂北 | 来源:发表于2019-03-01 16:46 被阅读20次

    1.iOS调用js方法

    • 先看下js的方法
    function methodName(parameter) {
        alert(parameter);
    }
    

    上面就是js的方法,methodName是方法名由iOS和js双方约定,括号里就是参数,传什么参数也是由双方约定好的。

    • 下面是iOS调用js的方法(共有两种方法)
      方法一:
    [webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"methodName('%@')", parameter]];
    

    webview:是你自己创建的UIWebview
    methodName:js方法名
    parameter:传给js的参数

    这个方法需要写在webview加载完网页后才会生效。如果网页还没加载完就调用这个方法去调用js的方法,那么是调不到的。所以想在网页刚加载的时候或者在加载途中就调用js方法传参是不可能实现的。

    这个方法比较适合给js传些简单的字符串参数,数组、字典、json字符串、对象这些是传不过去的。

    如果js方法有多个参数,iOS在调用js方法传参时多个参数用,隔开。例如:
    js方法

    function methodName(parameter1, parameter2) {
        alert(parameter1);
    }
    

    iOS调用

    [webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"methodName('%@','%@')", parameter1, parameter2]];
    
    • 方法二(js方法就不写了,跟上面一样的)
      iOS调用
    //获取js上下文环境
    JSContext * context = [self.webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
    
    JSValue * action = context[@"methodName"];
    [action callWithArguments:@[parameter1, parameter2]];
    

    methodName:js方法名
    parameter1:参数1
    parameter2:参数2

    这个调用js的方法需要注意的是参数必须写在数组里

    ios调用js方法.png
    /*!
    @method
    @abstract Invoke a JSValue as a function.
    @discussion In JavaScript, if a function doesn't explicitly return a value then it
     implicitly returns the JavaScript value <code>undefined</code>.
    @param arguments The arguments to pass to the function.
    @result The return value of the function call. 
    */
    - (JSValue *)callWithArguments:(NSArray *)arguments;
    

    大家可以看到这个方法要求的就是数组。而并不是js要求传数组

    这个方法也是不能传oc的一些对象的,因为语法的不同所以js并不认识oc的对象,但是json是双方都认识的,所以一些复杂的数据可以用json字符串传

    2.js调用iOS

    • 1.最简单直接的方法是拦截url
      先看下js端是怎么写的
    window.location.href = 'methodName://';
    

    methodName:// 这个是ios和js双方自己商量好的。这个是把http://改成了methodName://,当然//后面也可以有别的内容,这个就是看你们双方是怎么定的了。

    ios端拦截url并做一些相应的操作

    - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{
        
        //获取url
        NSString * requestStr = request.URL.absoluteString;
        NSLog(@"URL:%@",requestStr);
        
        //request.URL.scheme协议头   就是methodName
        if ([request.URL.scheme isEqualToString:@"methodName"]){
            return NO;
        }
        
        return YES;
    }
    

    上面这个方法是webview的一个代理方法。webview在开始加载网页的时候都会走这个方法,在这个方法里可以获取到网页的url。js的window.location.href = 'methodName://'这个方法就是网页加载url的方法,所以js一执行这个方法ios这边的方法就能拦截到。

    在方法中需返回YES和NO,如果返回YES则网页继续加载,否则就不加载。因为methodName://这个url是错误的,我们只是想通过这个调用oc而不是真的去加载这个错误的url所以在拦截到了methodName://后返回NO。

    上面oc方法中
    NSString * requestStr = request.URL.absoluteString;
    NSLog(@"URL:%@",requestStr);
    这个是获取url
    if ([request.URL.scheme isEqualToString:@"methodName"]){
    //这里做oc相应的操作
    return NO;
    }
    这个是根据协议头来判断是不是methodName://

    • 2.js调用iOS方法二
    // 获取webview上的js
    JSContext *context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
    
    // methodName是方法名
    context[@"methodName"] = ^(){
            NSArray *args = [JSContext currentArguments];//js传过来的参数
            NSLog(@"第一个参数=%@",[args[0] toString]);
            NSLog(@"第二个参数=%@",[args[1] toString]);
            dispatch_async(dispatch_get_main_queue(), ^{
                //oc做相应的操作
            });
        };
    

    这个方法写在哪里呢?

    • 只要网页加载完以后调用都是可以的。当然最好是写在-(void)webViewDidFinishLoad:(UIWebView *)webView这个方法里

    上面这个是oc注册方法给js调用,方法名就是methodName。
    NSArray *args = [JSContext currentArguments];是js传过来的参数,js那边传过来的不是数组,而是这个[JSContext currentArguments]方法把参数转化成了数组。下面先看下js是怎么调用的,就是知道参数是怎么回事了。

    methodName(parameter1, parameter2);
    

    这个就是js调用oc的方法,methodName是方法名,parameter1和parameter2是两个参数,参数是双方定好的,可以传一个参数也可以多个,多个参数就用,隔开。

    js端传的是这两个参数,但在oc端接收的时候却是以数组形式接受的NSArray *args = [JSContext currentArguments];
    所以args数组中args[0]就是第一个参数。但是args里包含元素是JSValue,并不是oc中的字符串什么的,所以还得转化一下。
    转化为字符串:[args[0] toString]
    下面是转化为各种类型的方法

    - (id)toObject;
    
    /*!
    @method
    @abstract Convert a JSValue to an Objective-C object of a specific class.
    @discussion The JSValue is converted to an Objective-C object of the specified Class. 
     If the result is not of the specified Class then <code>nil</code> will be returned.
    @result An Objective-C object of the specified Class or <code>nil</code>.
    */
    - (id)toObjectOfClass:(Class)expectedClass;
    
    /*!
    @method
    @abstract Convert a JSValue to a boolean.
    @discussion The JSValue is converted to a boolean according to the rules specified 
     by the JavaScript language.
    @result The boolean result of the conversion.
    */
    - (BOOL)toBool;
    
    /*!
    @method
    @abstract Convert a JSValue to a double.
    @discussion The JSValue is converted to a number according to the rules specified 
     by the JavaScript language.
    @result The double result of the conversion.
    */
    - (double)toDouble;
    
    /*!
    @method
    @abstract Convert a JSValue to an <code>int32_t</code>.
    @discussion The JSValue is converted to an integer according to the rules specified 
     by the JavaScript language.
    @result The <code>int32_t</code> result of the conversion.
    */
    - (int32_t)toInt32;
    
    /*!
    @method
    @abstract Convert a JSValue to a <code>uint32_t</code>.
    @discussion The JSValue is converted to an integer according to the rules specified 
     by the JavaScript language.
    @result The <code>uint32_t</code> result of the conversion.
    */
    - (uint32_t)toUInt32;
    
    /*!
    @method
    @abstract Convert a JSValue to a NSNumber.
    @discussion If the JSValue represents a boolean, a NSNumber value of YES or NO 
     will be returned. For all other types the value will be converted to a number according 
     to the rules specified by the JavaScript language.
    @result The NSNumber result of the conversion.
    */
    - (NSNumber *)toNumber;
    
    /*!
    @method
    @abstract Convert a JSValue to a NSString.
    @discussion The JSValue is converted to a string according to the rules specified 
     by the JavaScript language.
    @result The NSString containing the result of the conversion.
    */
    - (NSString *)toString;
    
    /*!
    @method
    @abstract Convert a JSValue to a NSDate.
    @discussion The value is converted to a number representing a time interval 
     since 1970 which is then used to create a new NSDate instance.
    @result The NSDate created using the converted time interval.
    */
    - (NSDate *)toDate;
    
    /*!
    @method
    @abstract Convert a JSValue to a NSArray.
    @discussion If the value is <code>null</code> or <code>undefined</code> then <code>nil</code> is returned.
     If the value is not an object then a JavaScript TypeError will be thrown.
     The property <code>length</code> is read from the object, converted to an unsigned
     integer, and an NSArray of this size is allocated. Properties corresponding
     to indicies within the array bounds will be copied to the array, with
     JSValues converted to equivalent Objective-C objects as specified.
    @result The NSArray containing the recursively converted contents of the 
     converted JavaScript array.
    */
    - (NSArray *)toArray;
    
    /*!
    @method
    @abstract Convert a JSValue to a NSDictionary.
    @discussion If the value is <code>null</code> or <code>undefined</code> then <code>nil</code> is returned.
     If the value is not an object then a JavaScript TypeError will be thrown.
     All enumerable properties of the object are copied to the dictionary, with
     JSValues converted to equivalent Objective-C objects as specified.
    @result The NSDictionary containing the recursively converted contents of
     the converted JavaScript object.
    */
    - (NSDictionary *)toDictionary;
    

    3.oc调用js window.close方法

    • 先在webview加载完全的方法里注册下js
    // webview加载完毕
    -(void)webViewDidFinishLoad:(UIWebView *)webView{
        
        //将window.close转为back://   当js调用window.close时自动调用back://
        NSString *js = @"window.close = function() {window.location.assign(\"back://\");};";
        
        [webView stringByEvaluatingJavaScriptFromString:js];
        
    }
    

    将window.close转为back:// 当js调用window.close时自动调用back://,所以在代理方法中可以拦截到back://,然后再做相应的操作

    相关文章

      网友评论

        本文标题:webview与js交互

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