iOS关于web页面的javascript和OC交互

相信在开发的过程中很多页面已经开始慢慢的采用html5来处理了,数据的维护、管理;页面的布局、样式也开始慢慢的被h5渗透,这里不讨论到底开发是h5 app好还是native app 更好,这边对h5与OC的交互做下讲解,存在的就是合理的。

demo已经封装好,下载地址:https://github.com/pengjinguang521/webAndJSDemo.git

一、拦截http请求来处理交互事件

1、javascript的代码  这里面点击按钮时候掉用了打开网页的方法window.location.href="haleyAction://shareClick?title=text&content=content&url=http://www.baidu.com";

function shareClick()

{window.location.href="haleyAction://shareClick?title=text&content=content&url=http://www.baidu.com";

}

2、JS掉起iOS方法,在iOS端的代码使用了web的代理方法当webview加载页面的时候去截获到http的请求,拿到url,然后从url中获取我们所要的信息,或者获取我们所要做的事情

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{

NSURL *URL = request.URL;

NSString *scheme = [URL scheme];

if ([scheme isEqualToString:@"haleyaction"]) {

[self handleCustomAction:URL];

return NO;

}

return YES;

}

3、iOS掉起JS的方法,这边主要是使用web的- (nullable NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script;方法来实现的,包括传值,以及h5数据的返回,不过需要注意的是这边返回的是string类型

// 这边是js中的代码

function setLocation(location) {

document.getElementById("text1").value = location;

}

// 这边是ios中的代码

[self.webview stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"setLocation(%@);",@"123"]]

二、iOS 7.0以后的

1、开发的时候你只需要导入上面的头文件即可

2、h5中的js代码,这边主要是三个方法:

       1. ios掉起js的方法并获取返回值。

       2.向js传入参数 

       3.点击按钮后传值出来

function postStr(){

return document.getElementById("text1").value;

}

function postValue(value){

document.getElementById("text1").value = value;

}

function buttonClick()

{

textlog("hello world");

}

3、客户端的代码实现主要是用JSContext *context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];context[@“textlog”]的方法,并拿到这个方法内的所有内容。

4、关于该方法掉起js的话,我觉得还是使用web的- (nullable NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script;方法来实现的,包括传值,以及h5数据的返回,不过需要注意的是这边返回的是string类型


三、WebViewJavascriptBridge框架

1、http://www.huangyibiao.com/archives/670  参考网址,这边主要从该博客习得

2、原理:我们看看WebViewJavascriptBridge.m中Webview代理拦截的代码:

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {

if (webView != _webView) { return YES; }

NSURL *url = [request URL];

__strong WVJB_WEBVIEW_DELEGATE_TYPE* strongDelegate = _webViewDelegate;

if ([_base isCorrectProcotocolScheme:url]) {

if ([_base isBridgeLoadedURL:url]) {

[_base injectJavascriptFile];

} else if ([_base isQueueMessageURL:url]) {

NSString *messageQueueString = [self _evaluateJavascript:[_base webViewJavascriptFetchQueyCommand]];

[_base flushMessageQueue:messageQueueString];

} else {

[_base logUnkownMessage:url];

}

return NO;

} else if (strongDelegate && [strongDelegate respondsToSelector:@selector(webView:shouldStartLoadWithRequest:navigationType:)]) {

return [strongDelegate webView:webView shouldStartLoadWithRequest:request navigationType:navigationType];

} else {

return YES;

}

}

在拦截后,通过先通过-isBridgeLoadedURL:方法判断URL是否是需要bridge的URL,若是,则通过injectJavascriptFile方法注入JS;否则判断URL是否是队列消息,若是,则执行查询命令JS并刷新消息队列;最后,URL被识别为未知的消息。

3、在JS端,嵌入步骤是:

第一步:将下面的代码放在JS中:

/*这段代码是固定的,必须要放到js中*/

function setupWebViewJavascriptBridge(callback) {

if (window.WebViewJavascriptBridge) { return callback(WebViewJavascriptBridge); }

if (window.WVJBCallbacks) { return window.WVJBCallbacks.push(callback); }

window.WVJBCallbacks = [callback];

var WVJBIframe = document.createElement('iframe');

WVJBIframe.style.display = 'none';

WVJBIframe.src = 'wvjbscheme://__BRIDGE_LOADED__';

document.documentElement.appendChild(WVJBIframe);

setTimeout(function() { document.documentElement.removeChild(WVJBIframe) }, 0)

}

第二步:在下面的方法体里写相关JS代码:

setupWebViewJavascriptBridge(function(bridge) {

/* Initialize your app here */

所有与iOS交互的JS代码放这里!


})

下面是demo中放入的所有ios与js交互的代码,详见demo中index.html文件

var uniqueId = 1      function log(message, data) {        var log = document.getElementById('log')        var el = document.createElement('div')        el.className = 'logLine'        el.innerHTML = uniqueId++ + '. ' + message + ':

' + JSON.stringify(data)        if (log.children.length) {            log.insertBefore(el, log.children[0])        } else {          log.appendChild(el)        }      }      /* Initialize your app here */              /*我们在这注册一个js调用OC的方法,不带参数,且不用ObjC端反馈结果给JS:打开本demo对应的博文*/      bridge.registerHandler('openWebviewBridgeArticle', function() {          log("openWebviewBridgeArticle was called with by ObjC")      })      /*JS给ObjC提供公开的API,在ObjC端可以手动调用JS的这个API。接收ObjC传过来的参数,且可以回调ObjC*/      bridge.registerHandler('getUserInfos', function(data, responseCallback) {        log("Get user information from ObjC: ", data)        responseCallback({'userId': '123456', 'blog': '标哥的技术博客'})      })                                          /*JS给ObjC提供公开的API,ObjC端通过注册,就可以在JS端调用此API时,得到回调。ObjC端可以在处理完成后,反馈给JS,这样写就是在载入页面完成时就先调用*/      bridge.callHandler('getUserIdFromObjC', function(responseData) {        log("JS call ObjC's getUserIdFromObjC function, and js received response:", responseData)      })      document.getElementById('blogId').onclick = function (e) {        log('js call objc: getBlogNameFromObjC')        bridge.callHandler('getBlogNameFromObjC', {'blogURL': 'http://www.henishuo.com'}, function(response) {                          log('JS got response', response)                          })     }

4、在iOS端掉用如下:

/** JS掉起oc方法 */

[web.bridge registerHandler:@"getBlogNameFromObjC" handler:^(id data, WVJBResponseCallback responseCallback) {

NSLog(@"%@_____data",data);

if (responseCallback) {

responseCallback(@{@"blogName": @"标哥的技术博客"});

}

}];

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

/** OC掉起js方法 */

[web.bridge callHandler:@"getUserInfos" data:@{@"name": @"标哥"} responseCallback:^(id responseData) {

NSLog(@"from js: %@", responseData);

}];

});

demo已经封装好,下载地址:

https://github.com/pengjinguang521/webAndJSDemo.git,详见viewController中的test方法,如有不足还望雅正!下次将分享关于手机端千万级用户量的日志处理、闪退、页面访问情况,调试错误分析!

你可能感兴趣的:(iOS关于web页面的javascript和OC交互)