IOS7 before Objective-c, JavaScript
UIWebViewObject has the following methods
- (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script
The method can execute JavaScript a string and return the return value of the string type. For example:
UIWebView *webView = [[UIWebView alloc] init];// result == @"3"NSString *result = [webView stringByEvaluatingJavaScriptFromString:@"1+2"];// 调用js 对象的方法NSString *result2 = [webView stringByEvaluatingJavaScriptFromString: @"window.objectApis.doSomething(‘hello‘)"];
Disadvantages
The above methods have the following disadvantages:
- Return value type can only be string type
Objective-CThe string result needs to be deserialized
JavaScriptThe result may need to be serialized
JavaScriptwhen invoking the method of an object, it is troublesome to pass in parameters
Objective-CParameters need to be serialized
JavaScriptYou may need to deserialize a string parameter
// 调用js 对象的方法NSString *result2 = [webView stringByEvaluatingJavaScriptFromString: @"window.objectApis.doSomething(‘hello \" world‘)"];
JavaScript-Objective-c
URLRequest Intercept
In UIWebView the browser JavaScript , there is no related method that can be called by the associated interface Objective-C . It is generally used JavaScript in the browser environment to make a request to URL Objective-C intercept the request to get the idea of the request. Intercepts the request in the Objective-C implementation UIWebViewDelegate :
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{ NSString *url = request.URL; // if (url是自定义的JavaScript通信协议) { // // do something // // 返回 NO 以阻止 `URL` 的加载或者跳转 // return NO; // }}
Objective-CCan be webView:shouldStartLoadWithRequest:navigationType returned in a method NO to block URL the load or jump.
JavaScriptThere are a variety of different ways to make URL requests:
- location.href: Modify
window.location.href Replace with a synthetic url , such as async://method:args
- location.hash: Modify
window.location.hash
<A> click: Create a <A> element, assign click () Method
- IFRAME.SRC: Create a
iframe element, assignment src Properties
- XHR sync/async: Create a
xmlhttprequest objects, open () Set the relevant information and whether it is asynchronous, and call send () method makes a request
var Linknode = document.createelement ("a"), var pongurl;var xhr = new XMLHttpRequest (); var iframe = document.createelement ("iframe"); Iframe.style.display = "none"; function ping (mechanism, startTime) {pongurl = "pong://" + startTime; switch (mechanism) {//Location.href case Mechanism.LocationHref:location.href = Pongurl; Break Location.hash Case Mechanism.LocationHash:location.hash = "#" + Pongurl; Break <a> Click case Mechanism.LinkClick:linkNode.href = Pongurl; Linknode.click (); Break Iframe. src case Mechanism.FrameSrc:iframe.src = pongurl; Document.body.appendChild (IFRAME); Document.body.removeChild (IFRAME); Break XHR Sync/async case Mechanism.XhrSync:case Mechanism.XhrAsync:xhr.open ("GET", Pongurl, Mecha Nism = = Mechanism.xhrasync); Xhr.send (); Break }}
Monitoring cookies
In UIWebView , Objective-C events can be used NSHTTPCookieManagerCookiesChangedNotification to listen for changes in cookies.
NSNotificationCenter *center = NSNotificationCenter.defaultCenter;[defaultCenter addObserverForName:NSHTTPCookieManagerCookiesChangedNotification object:nil queue:nil usingBlock:^(NSNotification *notification) { NSHTTPCookieStorage *cookieStorage = notification.object; // do something with cookieStorage }];
When JavaScript modified document.cookie , Objective-C you can obtain information by analyzing the cookie.
Disadvantages
Whether URL you are requesting interception or listening to cookies, there are the following drawbacks:
- The entire process is asynchronous and cannot be synchronized
- The
JavaScript return value of objective-c processing cannot be obtained directly in
Objective-CThe call JavaScript layer implements its own API to get the return value
- Use
callback more trouble
- Need to
JavaScript implement on your own
IOS 7+
IOS7 introduced JavaScriptCore , yes JavaScript and Objective-C can interoperate.
Objective-CMethods that can be used to JSContext evalueScript() invoke the provided method JavaScript .
#import <JavaScriptCore/JavaScriptCore.h>...UIWebView *webView = [[UIWebView alloc] init];JSContext *jsContext = [webView valueForPath: @"documentView.webView.mainFrame.javaScriptContext"];// call javascript[jsContext evalueScript: @"window.objectApis.doSomething()"];
Assigning an JSExport object that implements a protocol directly to an JSContext object's properties exposes the method to JavaScript .
// provide obj-c apisWBNativeApis *nativeApis = [[WBNativeApis alloc] init];jsContext[@"nativeApis"] = nativeApis;// `WBNativeApis` Class#import <Foundation/Foundation.h>#import <JavaScriptCore/JavaScriptCore.h>@protocol NativeApis <JSExport>-(void) logMessage: (NSString *) message;-(NSString *) version;// 异步-(void) asyncPrint: (NSString *) message;// callback-(void) asyncPrint: (NSString *) message callback: (JSValue *) callback;@end@interface WBNativeApis : NSObject <NativeApis>@end
Using JavaScript the called API in a browser environment Objective-C
window.nativeApis.logMessage(‘A message from javascript!‘);window.asyncPrintCallback(‘Message from javascript!‘, function (data) { var div = document.createElement(‘div‘); div.innerText = "Send message to native ok and get data from native"; document.body.appendChild(div);});
JavaScriptCoreThe various types of data are transformed between different programming languages and can be manipulated directly.
Objective-C type | JavaScript type --------------------+--------------------- nil | undefined NSNull | null NSString | string NSNumber | number, boolean NSDictionary | Object object NSArray | Array object NSDate | Date object NSBlock (1) | Function object (1) id (2) | Wrapper object (2) Class (3) | Constructor object (3)
Performance testing
In the iphone 5S (iOS 7.1) simulator, test the various modes of communication the milliseconds (MS) time spent in a single communication.
| Method |
AVG |
Min |
Max |
| Location.href |
1.44 |
0.70 |
13.59 |
| Location.hash |
1.00 |
0.66 |
6.19 |
| <a> Click |
1.40 |
0.66 |
15.29 |
| Iframe.src |
1.47 |
1.05 |
5.41 |
| XHR Sync |
1.36 |
0.85 |
3.44 |
| XHR Async |
0.85 |
0.46 |
14.96 |
| Document.cookie |
0.42 |
0.21 |
1.59 |
| JavaScriptCore |
0.06 |
0.04 |
0.13 |
As you can see from the table, JavaScriptCore the best way to communicate is performance.
Compatibility
The compatibility of various modes of communication is as follows ( + indicates support, X indicates not supported):
| Method/device |
iOS4 |
iOS5 |
iOS6 |
iOS7 |
iOS8 |
| Location.href |
+ |
+ |
+ |
+ |
+ |
| Location.hash |
+ |
+ |
+ |
+ |
+ |
| <a> Click |
+ |
+ |
+ |
+ |
+ |
| Iframe.src |
+ |
+ |
+ |
+ |
+ |
| XHR Sync |
+ |
X |
+ |
+ |
+ |
| XHR Async |
+ |
X |
+ |
+ |
+ |
| Document.cookie |
+ |
+ |
+ |
+ |
X |
| JavaScriptCore |
X |
X |
X |
+ |
+ |
Wkwebview (IOS 8 +)
IOS 8 is introduced in a WKWebView WKWebView way that is not supported JavaScriptCore but provides a message handler way for JavaScript Objective-C communicating with.
The Objective-C WKWebView following method calls are used in JavaScript :
- (void)evaluateJavaScript:(NSString *)javaScriptString completionHandler:(void (^)(id, NSError *))completionHandler
If the JavaScript code is faulted, it can be completionHandler processed.
In the Objective-C register message handler:
// WKScriptMessageHandler protocol?- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{ NSLog(@"Message: %@", message.body);}[userContentController addScriptMessageHandler:handler name:@"myName"];
When JavaScript sending information to Objective-C :
// window.webkit.messageHandlers.<name>.postMessage();?function postMyMessage()? {? var message = { ‘message‘ : ‘Hello, World!‘, ‘numbers‘ : [ 1, 2, 3 ] };? window.webkit.messageHandlers.myName.postMessage(message);?}
Resources
- Http://blog.persistent.info/2013/10/a-faster-uiwebview-communication.html
- Https://github.com/mihaip/web-experiments/pull/1
- http://www.bignerdranch.com/blog/javascriptcore-example/
- Http://oscaraperez.com/blog_assets/JavaScript%20with%20iOS7.pdf
- Http://blog.impathic.com/post/64171814244/true-javascript-uiwebview-integration-in-ios7
JavaScript and objective-c Communication in UIWebView