縱觀所有iOS與H5交互的方案,有以下幾種:
第一種:有很多的app直接使用在webview的代理中通過攔截的方式與native進行交互,通常是通過攔截url scheme判斷是否是我們需要攔截處理的url及其所對應的要處理的功能是什么。任意版本都支持。
第二種:iOS7之后出了JavaScriptCore.framework用於與JS交互,但是不支持iOS6,對於還需要支持iOS6的app,就不能考慮這個了。若需要了解,看最后的推薦閱讀。
第三種:WebViewJavascriptBridge開源庫使用,本質上,它也是通過webview的代理攔截scheme,然后注入相應的JS。
第四種:react-native,這個沒玩過(與前三種不同)。
1、UIWebView 和 js 交互 【JavaScriptCore.framework】
ViewController.m:
#import "WebViewController.h" #import "WebViewModel.h" @interface WebViewController () <UIWebViewDelegate> @property (nonatomic, strong) UIWebView *webView; @property (nonatomic, strong) JSContext *jsContext; @property (nonatomic, strong) WebViewModel *model; @end @implementation WebViewController - (void)viewDidLoad { [super viewDidLoad]; [self.view addSubview:self.webView]; [self createButtons]; // // 一個JSContext對象,就類似於Js中的window,只需要創建一次即可。 // self.jsContext = [[JSContext alloc] init]; // // // jscontext可以直接執行JS代碼。 // [self.jsContext evaluateScript:@"var num = 10"]; // [self.jsContext evaluateScript:@"var squareFunc = function(value) { return value * 2 }"]; // // 計算正方形的面積 // JSValue *square = [self.jsContext evaluateScript:@"squareFunc(num)"]; // // // 也可以通過下標的方式獲取到方法 // JSValue *squareFunc = self.jsContext[@"squareFunc"]; // JSValue *value = [squareFunc callWithArguments:@[@"20"]]; // NSLog(@"%@", square.toNumber); // NSLog(@"%@", value.toNumber); } - (void)createButtons { NSArray *array = @[@"ocCallJS", @"ocCallJSWithString", //@"ocCallJSWithTitle:message", //@"ocCallJSWithDictionary", //@"ocCallJSWithArray" ]; NSInteger index = 0; for (NSString *string in array) { UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]; [button setTitleColor:[UIColor redColor] forState:UIControlStateNormal]; [button setTitle:string forState:UIControlStateNormal]; [button addTarget:self action:@selector(buttonAciton:) forControlEvents:UIControlEventTouchUpInside]; button.frame = CGRectMake(kScreenWidth-300, 100+(index * 50), 280, 30); button.layer.borderColor = [UIColor redColor].CGColor; button.layer.borderWidth = 1; button.layer.cornerRadius = 3; index ++; [self.view addSubview:button]; } } - (void)buttonAciton:(UIButton *)button { if ([button.currentTitle isEqualToString:@"ocCallJS"]) { [self.model ocCallJS]; }else if ([button.currentTitle isEqualToString:@"ocCallJSWithString"]) { [self.model ocCallJSWithString:@"myocString"]; }else if ([button.currentTitle isEqualToString:@"ocCallJSWithTitle:message"]) { // [self.model ocCallJSWithString]; }else if ([button.currentTitle isEqualToString:@"ocCallJSWithDictionary"]) { [self.model ocCallJSWithDictionary:@{@"title":@"myoctitle",@"message":@"myocmessage"}]; }else if ([button.currentTitle isEqualToString:@"ocCallJSWithArray"]) { [self.model ocCallJSWithArray:@[@"myoctitle",@"myocmessage",@"30"]]; } } - (UIWebView *)webView { if (_webView == nil) { _webView = [[UIWebView alloc] initWithFrame:self.view.bounds]; NSURL *url = [[NSBundle mainBundle] URLForResource:@"callEach" withExtension:@"html"]; [_webView loadRequest:[NSURLRequest requestWithURL:url]]; //忽略web頁面與_WebView組件的大小關系如果設置為YES可以執行縮放,但是web頁面加載出來的時候,就會縮小到UIWebView組件的大小 _webView.scalesPageToFit = NO; _webView.delegate = self; } return _webView; } #pragma mark - UIWebViewDelegate - (void)webViewDidFinishLoad:(UIWebView *)webView { self.jsContext = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]; WebViewModel *model = [[WebViewModel alloc] init]; self.jsContext[@"CallEachModel"] = model; model.jsContext = self.jsContext; model.webView = self.webView; model.currentVC = self; self.model = model; self.jsContext.exceptionHandler = ^(JSContext *context, JSValue *exceptionValue) { context.exception = exceptionValue; NSLog(@"異常信息:%@", exceptionValue); }; } - (void)webViewDidStartLoad:(UIWebView *)webView { } @end
model.h:
#import <Foundation/Foundation.h> @protocol WebViewJSExport <JSExport> /** 遵守了 協議后 這些方法就暴露給 js 調用 **/ /** jsCallOC **/ - (void)jsCallOC; - (void)jsCallOCWithString:(NSString *)string; //js調用時候取函數名就好了 不要冒號 jsCallOCWithTitleMessage - (void)jsCallOCWithTitle:(NSString *)title message:(NSString *)msg; - (void)jsCallOCWithDictionary:(NSDictionary *)dictionary; - (void)jsCallOCWithArray:(NSArray *)array; /** ocCallJS **/ - (void)ocCallJS; - (void)ocCallJSWithString:(NSString *)string; - (void)ocCallJSWithTitle:(NSString *)title message:(NSString *)message; - (void)ocCallJSWithDictionary:(NSDictionary *)dictionary; - (void)ocCallJSWithArray:(NSArray *)array; /** callEach **/ - (void)jsCallOCAndOCCallJSWithParams:(NSDictionary *)params; - (void)ocCallJSAndJSCallOCWithParams:(NSDictionary *)params; @end @class BaseViewController; @interface WebViewModel : NSObject <WebViewJSExport> @property (nonatomic, weak) JSContext *jsContext; @property (nonatomic, weak) UIWebView *webView; @property (nonatomic, weak) BaseViewController *currentVC; @end
model.m
#import "WebViewModel.h" #import "BaseViewController.h" @implementation WebViewModel #pragma mark - jsCallOC - (void)jsCallOC { dispatch_async(dispatch_get_main_queue(), ^{ UIAlertView *alert = [[UIAlertView alloc] initWithTitle:nil message:@"jsCallOC" delegate:nil cancelButtonTitle:@"I konw" otherButtonTitles:nil, nil]; [alert show]; }); } - (void)jsCallOCWithString:(NSString *)string { dispatch_async(dispatch_get_main_queue(), ^{ UIAlertView *alert = [[UIAlertView alloc] initWithTitle:string message:nil delegate:nil cancelButtonTitle:@"I konw" otherButtonTitles:nil, nil]; [alert show]; }); } - (void)jsCallOCWithTitle:(NSString *)title message:(NSString *)msg { dispatch_async(dispatch_get_main_queue(), ^{ UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title message:msg delegate:nil cancelButtonTitle:@"I konw" otherButtonTitles:nil, nil]; [alert show]; }); } - (void)jsCallOCWithDictionary:(NSDictionary *)dictionary { dispatch_async(dispatch_get_main_queue(), ^{ UIAlertView *alert = [[UIAlertView alloc] initWithTitle:dictionary[@"title"] message:dictionary[@"message"] delegate:nil cancelButtonTitle:@"I konw" otherButtonTitles:nil, nil]; [alert show]; }); NSLog(@"===== %@",dictionary); } - (void)jsCallOCWithArray:(NSArray *)array { dispatch_async(dispatch_get_main_queue(), ^{ UIAlertView *alert = [[UIAlertView alloc] initWithTitle:array[0] message:array[1] delegate:nil cancelButtonTitle:@"I konw" otherButtonTitles:nil, nil]; [alert show]; }); NSLog(@"===== %@",array); } #pragma mark - OCCallJS - (void)ocCallJS { JSValue *jsFunc = self.jsContext[@"func1"]; [jsFunc callWithArguments:nil]; } - (void)ocCallJSWithString:(NSString *)string { NSInteger arc = arc4random()%1000; JSValue *jsFunc = self.jsContext[@"func2"]; [jsFunc callWithArguments:@[@{@"title": @"change--> myoctitle", @"message": @(arc)}]]; } - (void)ocCallJSWithTitle:(NSString *)title message:(NSString *)message { } - (void)ocCallJSWithDictionary:(NSDictionary *)dictionary { } - (void)ocCallJSWithArray:(NSArray *)array { } #pragma mark - callEach - (void)jsCallOCAndOCCallJSWithParams:(NSDictionary *)params { [self.currentVC createTopView]; self.currentVC.field.text = params[@"title"]; [self.currentVC setBlock:^(NSString *string){ if (string != nil && string.length > 0) { JSValue *jsFunc = self.jsContext[@"func2"]; [jsFunc callWithArguments:@[@{@"title":@"js 調出來topView 輸入填充到html:" , @"message": string}]]; } }]; } - (void)ocCallJSAndJSCallOCWithParams:(NSDictionary *)params { JSValue *jsFunc = self.jsContext[@"func3"]; [jsFunc callWithArguments:@[@{@"title": @"myoctitle", @"message": @"myocmessage"}]]; } @end
github地址: https://github.com/lc081200/H5ObjCExample