美文网首页
iOS OC与JS交互(一)-- UIWebView

iOS OC与JS交互(一)-- UIWebView

作者: 淡定的笨鸟 | 来源:发表于2019-05-09 16:25 被阅读0次

    UIWebView实现OC调用JS有两种方式
    1、stringByEvaluatingJavaScriptFromString
    2、JavaScriptCore
    JS调用OC也有两种方式
    1、request的url拦截
    2、JavaScriptCore
    其实从这里就可以看出JavaScriptCore很棒。

    UIWebViewDemo

    先写html

    使用url拦截的方式需要提前定义好url的规则,这里的简单的定义个规则lfjstooc:///methodName/para1/para2(规则可以是各种各样的,只要你能拦截下来就行),先看一下我们预先写好的html文件

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="UTF-8">
                <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
                    <title>UIWebView中OC与JS交互</title>
                    </head>
        
        <style type="text/css">
            .button {
                background: #f5be14;
                margin: 10px;
                text-align: center;
                width: 300px;
                height: 44px;
                line-height: 44px;
                margin: 10px auto;
                border-radius: 5px;
            }
        #setImage {
            width: 200px;
            height: 200px;
            margin: 0 auto;
        }
        </style>
        
        <body>
            
            <div class="button" onclick="firstClick()">今晚打老虎</div>
            <div class="button" onclick="secondClick()">请用力的点我</div>
            <div class="button" onclick="thirdClick()">弹我弹我</div>
            <div class="button" onclick="forthClick()">选择图片</div>
            <div id="setImage"></div>
        </body>
        
        <script type="text/javascript">
            
            var prefixStandard = "LFJSToOC://";
            
            function getText(index) {
                return document.getElementsByClassName("button")[0].innerText;
            }
        
        function firstClick() {
            var action = "firstClick";
            var token = getText(0);
            setUrl(action, token);
        }
        
        function secondClick() {
            var action = "secondClick";
            var token = getText(1);
            setUrl(action, token);
        }
        
        function thirdClick() {
            var action = "thirdClick";
            var token = getText(2);
            setUrl(action, token);
        }
        
        function forthClick() {
            var action = "forthClick";
            var token = getText(3);
            setUrl(action, token);
        }
        
        function setUrl(action, token) {
            var url = prefixStandard + "/" + action + "/" + token;
            loadUrl(url);
        }
        
        function loadUrl(url) {
            window.location.href = url;
        }
        
        function showImageOnDiv(imageStr) {
            var imgDiv = document.getElementById("setImage");
            imgDiv.innerHTML = "<image style='width:200px;' src='data:image/png;base64,"+imageStr+"'>";
        }
        
            </script>
        
    </html>
    
    

    这里实现的效果是这样的


    HTML的效果

    我们想要做的是,点击不同的按钮,在源生弹窗显示按钮上的字。

    UIWebView

    1、UIWebView初始化

    self.webView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height-HOME_INDICATOR_HEIGHT)];
    self.webView.delegate = self;
    self.webView.backgroundColor = [UIColor whiteColor];
    [self.view addSubview:self.webView];
        
    //这里在加载本地的html文件
    NSURL *url = [[NSBundle mainBundle] URLForResource:@"UIWebView.html" withExtension:nil];
    NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
    [self.webView loadRequest:request];
    

    2、实现代理
    UIWebView的主要四个代理如下,

    //加载所有webview的请求数据,以及控制是否要加载,所以JS调用的拦截在这里实现。
    /*
    JS的UIWebViewNavigationType对应如下样式,可以根据业务需求更细致的判断。
    typedef NS_ENUM(NSInteger, UIWebViewNavigationType) {
        UIWebViewNavigationTypeLinkClicked,        点击
     UIWebViewNavigationTypeFormSubmitted,      提交
     UIWebViewNavigationTypeBackForward,        返回
     UIWebViewNavigationTypeReload,             刷新
     UIWebViewNavigationTypeFormResubmitted,    重复提交
     UIWebViewNavigationTypeOther               其他
    } API_UNAVAILABLE(tvos);
    */
    - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType API_DEPRECATED("No longer supported.", ios(2.0, 12.0));
    //开始加载
    - (void)webViewDidStartLoad:(UIWebView *)webView API_DEPRECATED("No longer supported.", ios(2.0, 12.0));
    //加载完成
    - (void)webViewDidFinishLoad:(UIWebView *)webView API_DEPRECATED("No longer supported.", ios(2.0, 12.0));
    //加载失败
    - (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error API_DEPRECATED("No longer supported.", ios(2.0, 12.0));
    
    JS调OC

    这里我们先用普通的方式"request拦截",我们都知道webView在调用一个Url之前会走- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType这个代理,我们看到有NSURLRequest这个类型的参数,而从这个request中可以获取到JS调用的url(lfjstooc:///methodName/para1/para2),于是我们的故事开始了。
    1、request.URL.scheme
    我们通过scheme路由发放响应

    if ([request.URL.scheme.lowercaseString isEqualToString:@"lfjstooc"]) {
        return NO;//webview停止继续加载
    }
    

    2、request.URL.pathComponents
    通过pathComponents获取函数名和参数

    NSArray *arr = request.URL.pathComponents;
    /*
    (
        "/",
        secondClick,//方法名
        "this is the message"//一个NSString类型参数
    )
    */
    

    3、调用OC方法
    当然调用OC方法可以有很多种,[self methodName]直接调也行,performSelector: withObject:这种方式也行,我这里用objc_msgSend

    objc_msgSend(self, sel, arr[2]);
    

    综上,我们- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType里面代码如下

    - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
        //拦截JS的回调
        if ([request.URL.scheme.lowercaseString isEqualToString:@"lfjstooc"]) {
            NSArray *arr = request.URL.pathComponents;
            SEL sel = NULL;
            if (arr.count > 2) {//表示调用js调用的方法有参数
                sel = NSSelectorFromString([NSString stringWithFormat:@"%@:",arr[1]]);
            } else if(arr.count == 2) {//js调用OC,数组中至少得有两个元素
                sel = NSSelectorFromString(arr[1]);
            }
            objc_msgSend(self, sel, arr[2]);//调用对应的OC方法
            
            return NO;
        }
        
        return YES;
    }
    
    OC调JS

    OC调JS我们选择用UIWebView的stringByEvaluatingJavaScriptFromString方法,比如调用js的docoument.title方法获取当前页面的标题。

    NSString *title = [webView stringByEvaluatingJavaScriptFromString:@"document.title"];
        self.title = title;
    

    下面举一个点击html页面的按钮调用源生的系统相册选择图片,并把图片放到html页面的例子,代码如下
    首先响应JS调用的源生相册

    //第四个按钮点击事件,调用系统相册
    - (void)forthClick:(NSString *)str {
        if (!self.imagePicker) {
            self.imagePicker = [[UIImagePickerController alloc] init];
        }
        self.imagePicker.delegate = self;
        self.imagePicker.allowsEditing = YES;
        self.imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
        [self presentViewController:self.imagePicker animated:YES completion:nil];
    }
    

    其次实现照片选择完毕的系统代理- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info

    #pragma mark -- UIImagePickerDelegate
    - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info {
        NSLog(@"info---%@",info);
        UIImage *resultImage = [info objectForKey:@"UIImagePickerControllerOriginalImage"];
        NSData *imgData = UIImageJPEGRepresentation(resultImage, 0.01);
        NSString *encodedImageStr = [imgData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
        [self dismissViewControllerAnimated:YES completion:nil];
        NSString *imageString = [self clearImageString:encodedImageStr];
        
        NSString *jsFunctStr = [NSString stringWithFormat:@"showImageOnDiv('%@')",imageString];
        //OC调用JS
        [self.webView stringByEvaluatingJavaScriptFromString:jsFunctStr];
    }
    
    //清除base64串里面的东西
    - (NSString *)clearImageString:(NSString *)str {
        NSString *temp = [str stringByReplacingOccurrencesOfString:@" " withString:@""];
        temp = [temp stringByReplacingOccurrencesOfString:@"\r" withString:@""];
        temp = [temp stringByReplacingOccurrencesOfString:@"\n" withString:@""];
        return temp;
    }
    

    效果如下:


    JS与OC交互-选择系统相册.gif

    OK,以上就是UIWebView中OC与JS交互的内容,这种是比较简单的OC与JS交互,针对简单的业务使用起来很方便。

    相关文章

      网友评论

          本文标题:iOS OC与JS交互(一)-- UIWebView

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