1.HTML调用iOS中的方法
方法一:通过拦截点击方法的href.(你可以这样理解:点击网页中的一个按钮跳转到百度首页,其实这个按钮的href属性就是href = 'http://www.baidu.com')
//在webView的代理方法中根据URL来判断是否需要调用iOS中的方法
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{
NSLog(@"%@", request.URL.absoluteString);
// HTML中跳转,事件等操作都会携带一个URL,并且在这里都会截取到。和前端同事商量共同规定这一协议(当然可以随意)
NSString *str = request.URL.absoluteString;
// @"ecm:///openCamera"
NSRange range = [str rangeOfString:@"ecm:///"];
NSUInteger location = range.location;
if (location != NSNotFound) {// 取到指定的协议头时执行相应的方法
NSString *method = [str substringFromIndex:location + range.length];
SEL sel = NSSelectorFromString(method);
[self performSelector:sel];
}
return YES;
}
方法二:JSExport 协议关联 native对象,进而调用对象协议中约定的方法
需求描述:在A控制器,当点击一个按钮后跳转到B控制器,B控制器通过UIWebView加载一个后端用js写好的页面。此时,我们在点击页面上的关闭按钮返回到我们的A控制器。
分析:A控制器是我们客户端写的,而B控制器虽然是我们写的,但是加载的网页不是我们写的,所在在点击网页上的按钮时,就需要调用我们OC的方法来实现返回到A控制器。
//
// VertyCodeController.h
// Ecm
//
// Created by zengchunjun on 16/10/26.
//
#import <UIKit/UIKit.h>
#import <JavaScriptCore/JavaScriptCore.h>
// 定义一个遵循JSExport协议的协议。方法名必须与js调用的方法名一致,下面是我实际工作中的一个简单需求。若带有参数的方法,则我们定义的协议的方法可以随意拆分但是组合在一起也必须和js调用的方法名一致
@protocol vertyCodeJSProtocol <JSExport>
- (void)closeView;
@end
@interface VertyCodeController : UIViewController
@end
//
// VertyCodeController.m
// Ecm
//
// Created by zengchunjun on 16/10/26.
//
//
#import "VertyCodeController.h"
#import "Util.h"
#import "LoginView.h"
// 遵守定义的协议,实现相应的方法。
@interface VertyCodeController ()<UIWebViewDelegate,vertyCodeJSProtocol>
@property (nonatomic,weak)UIWebView *webView;
@property (nonatomic,strong)JSContext *context;
@end
@implementation VertyCodeController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view
self.view.backgroundColor = [UIColor whiteColor];
self.title = @"登录验证";
UIWebView *webView = [UIWebView new];
webView.frame = self.view.frame;
self.webView = webView;
self.webView.delegate = self;
[self.view addSubview:self.webView];
NSString *codeUrl = @"需要打开的网页"; // [Util getMessage_register_code_url];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:url]];
[self.webView loadRequest:request];
}
- (void)closeView
{
[LoginView Instance].stateText.text = @"验证通过,请重新登录";
[self dismissViewControllerAnimated:YES completion:nil];
}
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
// JSExport 协议关联 native对象,进而调用对象协议中约定的方法
// 获取该UIWebview的javascript执行环境。
self.context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
// 异常处理
self.context.exceptionHandler =
^(JSContext *context, JSValue *exceptionValue)
{
context.exception = exceptionValue;
NSLog(@"%@", exceptionValue);
};
// 其实服务端在点击关闭按钮时调用的方法就是 ecm.closeView()
// 带一个参数ecm.returnOneParame(str),则我们协议中定义的方法就需要写成 - (void)returnoneparamwe:(NSString *)str
// 带两个参数ecm.returnfirstsecond(str1,str2),则我们协议中定义的方法就需要写成 - (void)returnfirst:(NSString *)str1 second:(NSString *)str2;总结,方法名保持一致
self.context[@"ecm"] = self;
}
@end
//实现访问相册
- (void)openCamera{
UIImagePickerController *pickerVC = [[UIImagePickerController alloc] init];
pickerVC.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
[self presentViewController:pickerVC animated:YES completion:nil];
}
2.当HTML调用iOS中方法后,一般会传数据给服务端,这时就需要iOS调用HTML的方法
iOS 中调用HTML的方法用stringByEvaluatingJavaScriptFromString
// js交互,oc调用js方法
- (void)passValues:(NSArray *)list
{
//根据服务端的数据格式要求整理数据
NSMutableArray *dataArray = [NSMutableArray array];
for (int i = 0; i < list.count; i++) {
Contact *contact = list[i];
NSString *account = contact.account;
[dataArray addObject:account];
}
NSDictionary *dataDic = @{@"data":dataArray,@"message":@"调用成功",@"status":@0};
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dataDic options:NSJSONWritingPrettyPrinted error:nil];
NSString *jsonStr = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
// 直接调用HTML的方法括号内是需要传递的参数
[self.webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"selectedUsersComplete(%@)",jsonStr]];
}