zoukankan      html  css  js  c++  java
  • iOS原生APP和H5交互-delegate和第三方

    一、原生代中直接加载页面(拦截)

    1.    具体案例

    加载本地/网络HTML5作为功能介绍页

    2.    示例

    //本地

    -(void)loadLocalPage:(UIWebView*)webView

    {

       NSString* htmlPath = [[NSBundle mainBundle]pathForResource:@"demo" ofType:@"html"];

    NSString* appHtml =[NSString stringWithContentsOfFile:htmlPath encoding:NSUTF8StringEncodingerror:nil];

    NSURL *baseURL = [NSURLfileURLWithPath:htmlPath];

     [webView loadHTMLString:appHtmlbaseURL:baseURL];

    }

     

    //网络

    -(void)loadWebPage:(UIWebView *)webView

    {

        NSURL *url = [NSURLURLWithString:@"http://www.baidu.com"];

        NSURLRequest *request = [NSURLRequestrequestWithURL:url];

        [webView loadRequest:request];

    }

     

    3.    额外操

    a  iOS中承载网页的容器是UIWebView,可以借助它的代理来监听网页加载情况;

    b  在加载过程中,我们还可以获取该网页中的meta值,例如代码:

    NSString *shareUrl = [messWebViewstringByEvaluatingJavaScriptFromString:@"document.getElementsByName("shareUrl")[0].content"];

     

    就是从meta中得到shareUrl对应的value值;

    c  截获当前是发起的那种请求,以便native来做对应的控制,例如代码:

    - (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest *)requestnavigationType:(UIWebViewNavigationType)navigationType

    {

        NSString *requestString = [[[request URL]absoluteString]stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

        if ([requestString hasPrefix:@"http://customersharetrigger"]){

           //执行一些操作

            return NO;

        }

        return YES;

    } //可以监听到这个请求,从而达到控制作用;

     

     

    二、  原生代操作面元素(拦截)

    1.    具体案例

    在嵌入H5后需要操作页面元素

    2.    示例

    a、获取当前页面的url。

    -(void)webViewDidFinishLoad:(UIWebView *)webView {

      NSString *currentURL = [webView stringByEvaluatingJavaScriptFromString:@"document.location.href"];

    }

     

    b、获取页面title:

      NSString *currentURL = [webViewstringByEvaluatingJavaScriptFromString:@"document.location.href"];

     

       NSString *title = [webviewstringByEvaluatingJavaScriptFromString:@"document.title"];

     

    c、修改界面元素的值。

        NSString *js_result = [webViewstringByEvaluatingJavaScriptFromString:@"document.getElementsByName('q')[0].value='朱祁林';"];

    d、表单提交:

       NSString *js_result2 =[webView stringByEvaluatingJavaScriptFromString:@"document.forms[0].submit();"];

    3.    码说

    stringByEvaluatingJavaScriptFromString方法可以将javascript代码片段嵌入到页面中,通过这个方法就可以让iOS与UIWebView中的网页元素交互,例如上面的代码片段,它

    功能非常的强大,用起来也相对简单,通过它我们可以很方便的操作页面元素,而且能直接插入一段JS方法,然后调用该方法执行;

      

    三、  原生代码处理本地H5+JS(WebViewJavascriptBridge第三方)

    1.    具体案例

    需要动态显示曲线图,如果直接加载绘制图形特别慢,所以采用本地放置模板,传入参数,然后模板自动绘制,提高体验,加快绘制;

    2.    示例代

    -(void)loadWebPage:(UIWebView *)webView

    {

        NSURL *localPathURL = [[NSBundlemainBundle] URLForResource:@"detail" withExtension:@"html"subdirectory:@"htmlResources"];

        NSString *localPathUrl = [localPathURLabsoluteString];

        NSString *localParamPathUrl = [NSStringstringWithFormat:@"%@?symbol=%@&t=%f",localPathUrl,self.stockCode,self.time];

        NSURL *requestURL = [NSURLURLWithString:localParamPathUrl];

        [webView loadRequest:[NSURLRequestrequestWithURL:requestURL]];

     

    }

     

    3.    码说

    a 这里需要采用绝对路径拖入H5模板,就是选择CreateFolder Reference, 只有这样才能保证H5能调用到本地的JS代码,不然加载不成功,这个最初找了很多原因,最后才发现是拖入时候选择问题;

    b 如果要加入参数,注意需要先转成string,然后再转为URL;

      

    四、  原生代与网交互通信(WebViewJavascriptBridge第三方)

    1.    具体案例

    原生代码与H5相互调用方法,并传递参数,而且能回调数据;

    2.    借助第三方实现

    WebViewJavascriptBridge,该开源库非常完美的解决了原生代码与H5交互,即互殴;

    3.    示例

    1.初始化一个webview(viewdidload)

     

    UIWebView* webView =[[UIWebView alloc] initWithFrame:self.view.bounds];

        [self.view addSubview:webView];

     

     2.将此webview与WebViewJavascriptBridge关联(viewdidload)

     

    if (_bridge) { return; }

     

      [WebViewJavascriptBridge enableLogging];

     

      _bridge = [WebViewJavascriptBridgebridgeForWebView:webView webViewDelegate:self handler:^(id data,WVJBResponseCallback responseCallback) {

        NSLog(@"ObjC received message from JS:%@", data);

      

        responseCallback(@"Response formessage from ObjC");

      }];

     

    此时webview就与js搭上桥了。下面就是方法的互调和参数的互传。

     

     (1) js调oc方法(可以通过data给oc方法传值,使用responseCallback将值再返回给js)

     

    [_bridgeregisterHandler:@"testObjcCallback" handler:^(id data,WVJBResponseCallback responseCallback) {

            NSLog(@"testObjcCallback called:%@", data);

            responseCallback(@"Response fromtestObjcCallback");

        }];

     

      这里注意testObjcCallback这个方法的标示。html那边的命名要跟ios这边相同,才能调到这个方法。当然这个名字可以两边商量着自定义。简单明确即可。

     

      (2)oc调js方法(通过data可以传值,通过 response可以接受js那边的返回值 )

     

    id data = @{@"greetingFromObjC": @"Hi there, JS!" };

        [_bridgecallHandler:@"testJavascriptHandler" data:data responseCallback:^(idresponse) {

            NSLog(@"testJavascriptHandlerresponded: %@", response);

        }];

     

     注意这里的 testJavascriptHandler也是个方法标示。

     (3)oc给js传值(通过 response接受返回值 )

     

    [_bridge send:@"Astring sent from ObjC to JS" responseCallback:^(id response) {

            NSLog(@"sendMessage got response:%@", response);

        }];

     

      (4)oc给js传值(无返回值)

     

    [_bridge send:@"A string sent from ObjC after Webview hasloaded."];

     

    五、UIWebView页面信息的离线缓存

    推荐一个比较好的第三方库RNCachingURLProtocol ,只需要在AppDelegate中加入下面方法即可。

    [NSURLProtocolregisterClass:[RNCachingURLProtocolclass]];

    地址:https://github.com/rnapier/RNCachingURLProtocol

     

    六、 总结

    关于Native和H5的交互有各种形式,随着H5越来越成熟,未来的趋势就是两者形影不离,让App更具灵活性和实效性,也一定程度上提高了开发效率和迭代周期,是企业级移动应用开发的必选解决方案,推荐:IT面试宝典(典型)。

    版权声明:本文为博主原创文章,未经博主允许不得转载。

    七、附加 JS端配置:(WebViewJavascriptBridge第三方)

    <!doctype html>
    <html>
        <head>
        <meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1.0, maximum-scale=1.0">
        <style type='text/css'>
            html { font-family:Helvetica; color:#222; }
            h1 { color:steelblue; font-size:24px; margin-top:24px; }
            button { margin:0 3px 10px; font-size:12px; }
            .logLine { border-bottom:1px solid #ccc; padding:4px 2px; font-family:courier; font-size:11px; }
        </style>
        </head>
    
    <body>
        <h1>WebViewJavascriptBridge Demo</h1>
        <script>
        window.onerror = function(err) {
            log('window.onerror: ' + err)
        }
        /*这段代码固定的要放到js中*/
        function setupWebViewJavascriptBridge(callback) {
            if (window.WebViewJavascriptBridge) { return callback(WebViewJavascriptBridge); }
            if (window.WVJBCallbacks) { return window.WVJBCallbacks.push(callback); }
            window.WVJBCallbacks = [callback];
            var WVJBIframe = document.createElement('iframe');
            WVJBIframe.style.display = 'none';
            WVJBIframe.src = 'wvjbscheme://__BRIDGE_LOADED__';
            document.documentElement.appendChild(WVJBIframe);
            setTimeout(function() { document.documentElement.removeChild(WVJBIframe) }, 0)
        }
    
        //与oc交互的所有方法都要放到这儿注册
        setupWebViewJavascriptBridge(function(bridge) {
            var uniqueId = 1
            function log(message, data) {
                var log = document.getElementById('log')
                var el = document.createElement('div')
                el.className = 'logLine'
                el.innerHTML = uniqueId++ + '. ' + message + ':<br/>' + JSON.stringify(data)
                if (log.children.length) { log.insertBefore(el, log.children[0]) }
                else { log.appendChild(el) }
            }
                                     
            /*JS给ObjC提供公开的API,在ObjC端可以手动调用JS的这个API。接收ObjC传过来的参数,且可以回调ObjC*/
            bridge.registerHandler('testJavascriptHandler', function(data, responseCallback) {
                log('ObjC called testJavascriptHandler with', data)
                var responseData = { 'Javascript Says':'Right back atcha!' }
                log('JS responding with', responseData)
                responseCallback(responseData)
            })
    
            document.body.appendChild(document.createElement('br'))
    
            var callbackButton = document.getElementById('buttons').appendChild(document.createElement('button'))
            callbackButton.innerHTML = 'Fire testObjcCallback'
            callbackButton.onclick = function(e) {
                e.preventDefault()
                log('JS calling handler "testObjcCallback"')
                /*JS给ObjC提供公开的API,ObjC端通过注册,就可以在JS端调用此API时,得到回调。ObjC端可以在处理完成后,反馈给JS,这样写就是在载入页面完成时就先调用*/
                bridge.callHandler('testObjcCallback', {'foo': 'bar'}, function(response) {
                    log('JS got response', response)
                })
            }
        })
        </script>
        <div id='buttons'></div>
        <div id='log'></div>
    </body>
    
    </html>

     github测试demo:https://github.com/n1sunjianfei/iOS-And-H5

     参考文献:http://www.myexception.cn/operating-system/1977272.html

                   http://www.jianshu.com/p/4ed3e5ed99c6

    推荐阅读:http://www.cnblogs.com/jiang-xiao-yan/p/5345755.html

             

  • 相关阅读:
    Nginx 部署多个 web 项目(虚拟主机)
    Nginx 配置文件
    Linux 安装 nginx
    Linux 安装 tomcat
    Linux 安装 Mysql 5.7.23
    Linux 安装 jdk8
    Linux 安装 lrzsz,使用 rz、sz 上传下载文件
    springMVC 拦截器
    spring 事务
    基于Aspectj 注解实现 spring AOP
  • 原文地址:https://www.cnblogs.com/sunjianfei/p/6086876.html
Copyright © 2011-2022 走看看