1.JS调用OC的方法
OC自定义一个协议 例如YBHTTP:。JS遵循这个协议,发出一个请求window.location.href=‘YBHTTP:http://www.baidu.com‘
OC在
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType 这个代理方法中拦截该请求 并根据之前规定好的协议解析这个请求,这样就知道JS要OC做什么事情,然后OC在做相应的事。相关代码仅供参考
#define kJSCallOCRequestDataHeader @"YBHTTP:" //js调用oc方法请求数据的协议头
#define kJSCallOCWebSocketHeader @"websocket:" //js调用oc方法 websocket相关
先说明一下 kJSCallOCRequestDataHeader kJSCallOCWebSocketHeader是定义好的宏 JSCallOCProtocol是我自己定义的一个模型 [JS_OC JSCallObjcWithJSCallOCProtocol:jsCallOCProtocol webView:webView]这个是我解析协议之后我OC要做的事
下面的代码解析了两个协议
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
NSString *url = [request.URL.absoluteString stringByRemovingPercentEncoding];
YBLog(@"%@", url);
if ([url hasPrefix:kJSCallOCRequestDataHeader])//判断url是否遵循了JS调用OC方法 请求数据协议
{
NSString *json = [url substringFromIndex:kJSCallOCRequestDataHeader.length];
NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:[json dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingAllowFragments error:nil];
NSString *url = [jsonDict[@"url"] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSString *method = [jsonDict[@"method"] lowercaseString];
NSString *callback = jsonDict[@"callback"];
NSDictionary *parameters = jsonDict[@"parameters"];
JSCallOCProtocol *jsCallOCProtocol = [JSCallOCProtocol jsCallOCProtocolWithURL:url method:method callback:callback parameters:parameters];
[JS_OC JSCallObjcWithJSCallOCProtocol:jsCallOCProtocol webView:webView];//JS调用OC的方法 这个是我自己自定义的 方法
return NO;//禁止加载该页面
}
else if ([url hasPrefix:kJSCallOCWebSocketHeader])//js调用oc websocket相关方法
{
NSString *json = [url substringFromIndex:kJSCallOCWebSocketHeader.length];
NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:[json dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingAllowFragments error:nil];
NSString *type = jsonDict[@"type"];
NSString *callback = jsonDict[@"callback"]; //js的回调方法
if ([type isEqualToString:@"getCurrentMessageCount"])//JS获取聊天未读信息总条数
{
[self.webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"%@(%zi, ‘ios‘)", callback, self.currentMessageCount]];
}
else if ([type isEqualToString:@"loginOut"])//用户退出登录
{
[self closeWebSocket];//断开websocket连接
//把本地保存的用户名密码 注销掉 即密码清空
[UserTool registerCurrentUser];
}
else if ([type isEqualToString:@"messageCountSubOne"])//用户聊天条数减一
{
self.currentMessageCount--;
}
return NO;
}
return YES;
}
2.OC调用JS的方法
这个比较简单 只需JS定义一个全局的function函数 OC直接就可以调用 比如
[webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"%@(%@, ‘ios‘)", callback, jsonStr]];
这个方法就是调用JS的callback函数 并且该函数有两个参数 分别是jsonStr 和 ‘ios‘
3.OC拦截JS的Alert 和 Confirm
只需在OC里面新建一个UIWebView的分类,定义两个方法分别是
/**
* 拦截UIWebView中网页弹出的alert提示框
*
* @param sender UIWebView
* @param message 提示信息
*/
- (void)webView:(UIWebView *)sender runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(CGRect)frame;
/**
* 拦截UIWebView中网页弹出的confirm提示框
*
* @param sender UIWebView
* @param message 提示信息
*/
- (BOOL)webView:(UIWebView *)sender runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(CGRect)frame;
并且实现 代码如下
static BOOL diagStat = NO;
- (void)webView:(UIWebView *)sender runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(CGRect)frame {
UIAlertView* customAlert = [[UIAlertView alloc] initWithTitle:@"提示"
message:message
delegate:self
cancelButtonTitle:@"确定"
otherButtonTitles:nil];
[customAlert show];
}
- (BOOL)webView:(UIWebView *)sender runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(CGRect)frame
{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"提示"
message:message
delegate:self
cancelButtonTitle:@"取消"
otherButtonTitles:@"确定", nil];
[alertView show];
while (alertView.hidden == NO && alertView.superview != nil) {
[[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.01f]];
}
return diagStat;
}
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
if (buttonIndex==0) {
diagStat=YES;
}else if(buttonIndex==1){
diagStat=NO;
}
}
创建好这个分类之后 然后在你加载UIWebView的UIVIewCotroller中导入这个分类即可 会自动拦截JS的alert和Confirm 实现我们OC自己的方法 这个通常用来替换JS的alert提示框
4.取消UIWebView加载的网页 长按会弹出提示框 为了使其更像原生态 可以禁止掉 代码如下
#pragma mark 取消webView长按弹出copy菜单
- (void)cancelWebViewPopCopyMenu
{
self.webView.dataDetectorTypes = UIDataDetectorTypeNone;
[self.webView stringByEvaluatingJavaScriptFromString:@"document.body.style.webkitTouchCallout=‘none‘;"];
[self.webView stringByEvaluatingJavaScriptFromString:@"document.documentElement.style.webkitUserSelect=‘none‘;"];
}