金刚娃谈UIWebView与JS交互

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';"];

}

原文地址:https://www.cnblogs.com/bing-ge/p/4815602.html