IOS7 before Objective-c, JavaScript
UIWebView
Object 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-C
The string result needs to be deserialized
JavaScript
The result may need to be serialized
JavaScript
when invoking the method of an object, it is troublesome to pass in parameters
Objective-C
Parameters need to be serialized
JavaScript
You may need to deserialize a string parameter
// 调用js 对象的方法NSString *result2 = [webView stringByEvaluatingJavaScriptFromString: @"window.objectApis.doSomething(‘hello \" world‘)"];
JavaScript-Objective-c
URL
Request 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-C
Can be webView:shouldStartLoadWithRequest:navigationType
returned in a method NO
to block URL
the load or jump.
JavaScript
There 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-C
The 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-C
Methods 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);});
JavaScriptCore
The 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