Communication between JavaScript and Objective-C in UIWebView, uiwebview
Objective-C-> JavaScript before iOS7
UIWebView
The object has the following methods:
- (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script
This method can executeJavaScript
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"]; // call the js object method NSString * result2 = [webView stringByEvaluatingJavaScriptFromString: @ "window. objectApis. doSomething ('hello') "];
Disadvantages
The preceding methods have the following Disadvantages:
- The return value type can only be a string type.
Objective-C
Deserialization of string results is required
JavaScript
Serialization of results may be required
- Call
JavaScript
It is troublesome to pass in parameters when using object methods.
Objective-C
Parameters need to be serialized
JavaScript
String parameters may need to be deserialized.
// Call the js object method NSString * result2 = [webView stringByEvaluatingJavaScriptFromString: @ "window. objectApis. doSomething ('Hello \" World') "];
JavaScript-> Objective-C
URL
Request Interception
InUIWebView
In the browserJavaScript
No related interfaces can be called.Objective-C
. GenerallyJavaScript
Issue in the browser EnvironmentURL
Request,Objective-C
InObjective-C
In implementationUIWebViewDelegate
Request Interception:
-(BOOL) webView :( UIWebView *) webView shouldStartLoadWithRequest :( NSURLRequest *) request navigationType :( UIWebViewNavigationType) navigationType {NSString * url = request. URL; // if (the url is a custom JavaScript Communication Protocol) {// do something /// NO is returned to prevent the loading or redirection of 'url' // return NO ;//}}
Objective-C
You canwebView:shouldStartLoadWithRequest:navigationType
Method can returnNO
To blockURL
.
JavaScript
There are various methods for sendingURL
Request:
- Location. href: Modify
window.location.href
Replace it with a mergedURL
For exampleasync://method:args
- Location. hash: Modify
window.location.hash
<a>
Click: Create<a>
Element, value assignmenthref
And call itsclick()
Method
- Iframe. src: Create
iframe
Element, value assignmentsrc
Attribute
- XHR sync/async: Create
XMLHttpRequest
Object,open()
Set the relevant information and whether it is asynchronous, and callsend()
Method To send 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, mechanism == Mechanism.XhrAsync); xhr.send(); break; }}
Listener Cookie
InUIWebView
Medium,Objective-C
You can useNSHTTPCookieManagerCookiesChangedNotification
Event to listen for cookie changes.
NSNotificationCenter *center = NSNotificationCenter.defaultCenter;[defaultCenter addObserverForName:NSHTTPCookieManagerCookiesChangedNotification object:nil queue:nil usingBlock:^(NSNotification *notification) { NSHTTPCookieStorage *cookieStorage = notification.object; // do something with cookieStorage }];
WhenJavaScript
Modifydocument.cookie
After,Objective-C
You can analyze cookies to obtain information.
Disadvantages
Whether it isURL
Both Request Interception and Cookie listening methods have the following Disadvantages:
- The entire process is asynchronous and cannot be synchronized.
- In
JavaScript
Can not directly obtain the returned value of Objective-C Processing
- Yes
Objective-C
CallJavaScript
Only APIs implemented by the layer can get the returned value.
- Use
callback
Relatively troublesome
- You must
JavaScript
On your own
IOS 7 +
IOS7 introducedJavaScriptCore
YesJavaScript
AndObjective-C
Interoperability.
Objective-C
AvailableJSContext
OfevalueScript()
Method callJavaScript
Method provided.
#import <JavaScriptCore/JavaScriptCore.h>...UIWebView *webView = [[UIWebView alloc] init];JSContext *jsContext = [webView valueForPath: @"documentView.webView.mainFrame.javaScriptContext"];// call javascript[jsContext evalueScript: @"window.objectApis.doSomething()"];
ImplementJSExport
The object of the Protocol is directly assignedJSContext
The object property can be exposedJavaScript
.
// 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; // asynchronous-(void) asyncPrint: (NSString *) message; // callback-(void) asyncPrint: (NSString *) message callback: (JSValue *) callback; @ end @ interface WBNativeApis: NSObject <NativeApis> @ end
Use in a browser EnvironmentJavaScript
CallObjective-C
Api
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
Various types of data are converted between different programming languages and can be directly operated.
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
The millisecond (5S) time spent testing a variety of communication methods at one time in the iPhone MS (ios 7.1) simulator.
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 shown in the table,JavaScriptCore
The best communication performance.
Compatibility
The compatibility of various communication methods is as follows (+
Supported,X
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 IntroductionWKWebView
,WKWebView
Not SupportedJavaScriptCore
But the message handler method isJavaScript
AndObjective-C
Communication.
InObjective-C
Used inWKWebView
The following method is called:JavaScript
:
- (void)evaluateJavaScript:(NSString *)javaScriptString completionHandler:(void (^)(id, NSError *))completionHandler
IfJavaScript
Code error.completionHandler
Processing.
InObjective-C
To register message handler:
// WKScriptMessageHandler protocol
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{ NSLog(@"Message: %@", message.body);}[userContentController addScriptMessageHandler:handler name:@"myName"];
InJavaScript
Send informationObjective-C
:
// window.webkit.messageHandlers.<name>.postMessage();
function postMyMessage()
{
var message = { 'message' : 'Hello, World!', 'numbers' : [ 1, 2, 3 ] };
window.webkit.messageHandlers.myName.postMessage(message);
}
References
- 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