zoukankan      html  css  js  c++  java
  • UIWebView与JavaScript的交互

    总体概述:
          实质上oc与js的通信交互就是发送消息,也即函数调用,只要在交互的过程正确的指定好对方需要调用的函数和参数就ok
          oc-->js 
     stringByEvaluatingJavaScriptFromString,其参数是一NSString 字符串内容是js代码(这又可以是一个js函数、一句js代码或他们的组合),当js函数有返回值或一句js代码有值返回可通过stringByEvaluatingJavaScriptFromString的返回值获取
        js-->oc 利用webView的重定向原理(即重新在js中指定document.location的值,此为一url),只要在这个url字符串中按自定义的规则指定好所需调用oc中的函数和参数,然后通过OC中的shouldStartLoadWithRequest函数去捕获处理请求,处理完最后,如果js还想获取一些返回参数的话,同样让oc去通过stringByEvaluatingJavaScriptFromString调用刚js传过来的回调js函数就行,顺道把参数也一起传了,完美!!!

    UIWebView是IOS SDK中渲染网面的控件,在显示网页的时候,我们可以hack网页然后显示想显示的内容。其中就要用到javascript的知识,而UIWebView与javascript交互的方法就是stringByEvaluatingJavaScriptFromString:

    有了这个方法我们可以通过objc调用javascript,可以注入javascript。

    首先我们来看一下,如何调用javascript:

    1. [webView stringByEvaluatingJavaScriptFromString:@"myFunction();"];  

    备注: stringByEvaluatingJavaScriptFromString这个方法有个地方需要注意, 算不上bug, 但确实有问题, 需要注意!

    如果stringByEvaluatingJavaScriptFromString执行的是带参数的js函数, 这个参数里面如果带有( ')等等, js那边收不到这个值, 这些带的需要转义, 如下这么写js才能收到完整的消息

    message = [message stringByReplacingOccurrencesOfString:@" " withString:@"\\n"];

    NSString *jsMethod  = [NSString stringWithFormat:@"JsMethod("%@")", message];

    还有一个地方, 这2种写法看似一样, 实质不同, 如果是采用'引号, 如果message带有', 消息则传不过去! 所以最好采用"

    NSString *jsMethod  = [NSString stringWithFormat:@"JsMethod("%@")", message];

    NSString *jsMethod  = [NSString stringWithFormat:@"JsMethod('%@')", message];

     这儿myFunction()就是我们的javascript方法。

    再来看看入何注入javascript,我们先写一个需要注入的javascript:

    1. function showAlert() {  
    2.     alert('in show alert');  
    3. }  


    保存为test.js,然后拖到xcode 的resource分组下。再用代码在初始化的时候注入这个js(如在viewDidLoad方法里)。

    1. NSString *filePath = [[NSBundle mainBundle] pathForResource:@"test" ofType:@"js"];  
    2. NSString *jsString = [[NSString alloc] initWithContentsOfFile:filePath];  
    3. [webView stringByEvaluatingJavaScriptFromString:jsString];  


    这样就注入了上面的js,那么我们可以随时调用js的方法,如何调用,上面有介绍。

    那 么我们能不能通过js来调用objc的方法呢。 当然可以,原理就是利用UIWebView重定向请求,利用shouldStartLoadWithRequest可以捕获到uiwebview的一切请求! 如果我们在js里面发送一个特定的请求, 里面包含将要调用的oc函数和请求参数。

    首先我们写一个javascript 方法如下:

    1. function sendCommand(cmd,param){  
    2.     var url="testapp:"+cmd+":"+param;  
    3.     document.location = url;  
    4. }  
    5. function clickLink(){  
    6.     sendCommand("alert","你好吗?");  

    testapp是自己定义的一个协议, 只要不和http, https等国际通用协议头冲突都可以, 名字随便取;

    cmd是要调用的oc的方法;

    param是调用的参数

    然后利用document.location来达到目的!  上面的"testapp://"+cmd+":"+param是自定义的一种请求格式, 这个格式你也可以变, 比如可以像下面这样

    document.location="MyCustomProtocolName:functionName?param1=value1&param2=value2...".

    js里面怎么定义都可以, 怎么方便怎么来!  不过在shouldStartLoadWithRequest方法里面捕获到了这次请求后, 你要对应的解析, 判断是不是自己特定的请求!

    然后在你的html里调用这个js方法 如:

    1. "button" value="Click me!" onclick="clickLink()" />
    2. js文件里面 如果传出中文。要用到 js里面的 方法encodeURI 来处理一下。否则 xcode 中用 

      NSString* rurl=[[[request URL]  absoluteString]stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding ];  无法取得中文

       var url="protocol://"+encodeURI($("#textarea").val());


      url中含有中文,出现中文乱码(在oc代码中)
      //传输的时候这样写
        NSString *rateCardsName_CN=[[NSString stringWithFormat:@"%@",rateCardsName]stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

      //获取的时候这样写
      NSString *urlStr = [[request.URL absoluteString]stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; 


    最后我们在UIWebVew中截获这个重定向请求:

      1. #pragma mark --  
      2. #pragma mark UIWebViewDelegate  
      3.   
      4. - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {  
      5.       
      6.     NSString *requestString = [[[request URL]  absoluteString]stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding ]; 
      7. if ([rurl hasPrefix:@"testapp://"]) {    
      8.         //如果是自己定义的协议, 再截取协议中的方法和参数, 判断无误后在这里手动调用oc方法  
      9.     } 
      10.     return YES;  
      11. }  
  • 相关阅读:
    Shared Memory in Windows NT
    Layered Memory Management in Win32
    软件项目管理的75条建议
    Load pdbs when you need it
    Stray pointer 野指针
    About the Rebase and Bind operation in the production of software
    About "Serious Error: No RTTI Data"
    Realizing 4 GB of Address Space[MSDN]
    [bbk4397] 第1集 第一章 AMS介绍
    [bbk3204] 第67集 Chapter 17Monitoring and Detecting Lock Contention(00)
  • 原文地址:https://www.cnblogs.com/rongxiang/p/3835134.html
Copyright © 2011-2022 走看看