閱讀256 返回首頁    go 人物


H5和NA(WebView)的交互


H5和NA(WebView)的交互

URL攔截

NA->H5數據傳遞

使用stringByEvaluatingJavaScriptFromString,直接調用H5的函數名字,參數的json字符串:
例如:

- (void)webViewDidFinishLoad:(UIWebView *)webView {
    NSMutableDictionary *dictInfo = [NSMutableDictionary dictionary];
    [dictInfo setValue:@"value1" forKey:@"key1"];
   [dictInfo setValue:@"value2" forKey:@"key2"];
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dictInfo options:kNilOptions error:nil];
    if (jsonData) {
        NSString *strValueJson = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
        NSString *jsCode = [NSString stringWithFormat:@"picCallback&& picCallback(%@)", strValueJson];
        [webView stringByEvaluatingJavaScriptFromString:jsCode];
    } 
}

H5->NA數據傳遞

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
</head>
<body>
  <div >
      <h1>Objective-C和JavaScript交互的那些事</h1>
      <input type="button" value="CallCameraByUrl" >
  </div>
  <script>
      function callCameraByUrl(){
          window.location.href = 'toyun://callCamera';
      }
  </script>
</body>
</html>

window.location.href這裏是改變主窗口的指向從而馬上發出一個鏈接為Toyun://callCamera請求,而想要傳給原生應用的參數也可已包含到此請求中,而在iOS方法中我們要攔截這個請求,根據請求內容去判斷JavaStript想要做的事情,從而實現web頁麵和本地應用之間的交互


- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
    NSString *url = request.URL.absoluteString;
    if ([url rangeOfString:@"toyun://"].location != NSNotFound) {
            // url的協議頭是Toyun
        NSLog(@"callCamera");
        return NO;
    }
    return YES;
}

注意:url後麵可以拚接參數,參數的每個value要在H5裏麵單獨轉碼,避免特殊符號,&=以及中文.....

轉碼

H5的url上麵每個value要單獨進行encodeURIComponent的轉碼,之後再拚接成toyun://callCamera?key1=value1,比如:encodeURIComponent(value1)。

JS傳遞

H5代碼:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
</head>
<body>
  <div >
      <h1>Objective-C和JavaScript交互的那些事</h1>
      <input type="button" value="CallCamera" >
  </div>
  <div >
      <input type="button" value="share" >
  </div>
  <script type="text/javascript">
    function callShare()
    {
       var shareInfo = JSON.stringify({"title":"標題","desc":"內容","shareUrl":"https://www.jianshu.com/p/f896d73c670a"});
       Toyun.share(shareInfo); 
    }
  </script>
  <script>
    function picCallback(photos){
        alert(photos);
    }
  </script>
  <script>
    function shareCallback(){
      alert("success");
  }
  </script>
</body>
</html>

對H5稍作解釋:
先說Toyun是iOS和Android這兩邊在本地要注入的一個對象【參考下麵iOS的代碼更容易明白】,充當原生應用和web頁麵之間的一個橋梁。頁麵上定義了兩個按鈕名字分別為CallCamera和Share。
點擊CallCamera會調用Toyun最終橋梁對象的方法:callCamera()。而點擊Share會先調用本文件中的javascript方法callShared(),這裏將要分享的內容格式轉為Json字符串格式,然後再調用Toyun最終橋梁對象的方法: (void)share:(NSString *)shareInfo方法這個是有傳參的,參數為shareInfo。
而下麵的兩個方法為原生方法調用後的回調方法,其中picCallback為獲取圖片成功的回調方法,並且傳回拿到的圖片photos;shareCallback為分享成功的回調方法。

IOS:
JSContext:給JavaScript提供運行的上下文環境
JSValue:JavaScript和Objective-C數據和方法的橋梁
凡事添加了JSExport協議的協議,所規定的方法變量等,就會對js開放,我們可以通過JSContext調用到。

@protocol JSObjcDelegate <JSExport>
- (void)callCamera;
- (void)share:(NSString *)shareString;
@end

@interface ViewController : UIViewController
<UIWebViewDelegate,
JSObjcDelegate>

@property (nonatomic, strong) JSContext *jsContext;
@property (weak, nonatomic) IBOutlet UIWebView *webView;

@end

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    NSURL *url = [[NSBundle mainBundle] URLForResource:@"test" withExtension:@"html"];
    [self.webView loadRequest:[[NSURLRequest alloc] initWithURL:url]];
    self.webView.delegate = self;
}

#pragma mark - UIWebViewDelegate

- (void)webViewDidFinishLoad:(UIWebView *)webView {
    self.jsContext = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
    self.jsContext[@"Toyun"] = self;
    self.jsContext.exceptionHandler = ^(JSContext *context, JSValue *exceptionValue) {
        context.exception = exceptionValue;
        NSLog(@"異常信息:%@", exceptionValue);
    };
}

#pragma mark - JSObjcDelegate
- (void)callCamera {
    NSLog(@"callCamera");
        // 獲取到照片之後在回調js的方法picCallback把圖片傳出去
    JSValue *picCallback = self.jsContext[@"picCallback"];
    [picCallback callWithArguments:@[@"photos"]];
}

- (void)share:(NSString *)shareString {
    NSLog(@"share:%@", shareString);
        // 分享成功回調js的方法shareCallback
    JSValue *shareCallback = self.jsContext[@"shareCallback"];
    [shareCallback callWithArguments:nil];
}

@end

自定義JSObjcDelegate協議,而且此協議必須遵守JSExport這個協議,自定義協議中的方法就是暴露給web頁麵的方法:callCamera和share方法。
self.jsContext[@"Toyun"] = self;即把self賦值為名為Toyun的橋梁對象,則H5裏麵調用Toyun對象方法,即為此viewController處的方法。
在JavaStript調用完本地應用的方法做完相對應的事情之後,又回調了JavaStript中對應的方法,從而實現了web頁麵和本地應用之間的通訊。

最後更新:2017-08-13 22:34:14

  上一篇:go  數據挖掘——數據歸約之大型數據集的維度
  下一篇:go  機器學習資料