Communication between JavaScript and Objective-C in UIWebView, uiwebview
Objective-C-> JavaScript before iOS7
UIWebViewThe object has the following methods:
- (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script
This method can executeJavaScriptString 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-CDeserialization of string results is required
JavaScriptSerialization of results may be required
- Call
JavaScriptIt is troublesome to pass in parameters when using object methods.
Objective-CParameters need to be serialized
JavaScriptString parameters may need to be deserialized.
// Call the js object method NSString * result2 = [webView stringByEvaluatingJavaScriptFromString: @ "window. objectApis. doSomething ('Hello \" World') "];
JavaScript-> Objective-C
URLRequest Interception
InUIWebViewIn the browserJavaScriptNo related interfaces can be called.Objective-C. GenerallyJavaScriptIssue in the browser EnvironmentURLRequest,Objective-CInObjective-CIn implementationUIWebViewDelegateRequest 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-CYou canwebView:shouldStartLoadWithRequest:navigationTypeMethod can returnNOTo blockURL.
JavaScriptThere are various methods for sendingURLRequest:
- Location. href: Modify
window.location.hrefReplace it with a mergedURLFor exampleasync://method:args
- Location. hash: Modify
window.location.hash
<a>Click: Create<a>Element, value assignmenthrefAnd call itsclick()Method
- Iframe. src: Create
iframeElement, value assignmentsrcAttribute
- XHR sync/async: Create
XMLHttpRequestObject,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
InUIWebViewMedium,Objective-CYou can useNSHTTPCookieManagerCookiesChangedNotificationEvent 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 }];
WhenJavaScriptModifydocument.cookieAfter,Objective-CYou can analyze cookies to obtain information.
Disadvantages
Whether it isURLBoth Request Interception and Cookie listening methods have the following Disadvantages:
- The entire process is asynchronous and cannot be synchronized.
- In
JavaScriptCan not directly obtain the returned value of Objective-C Processing
- Yes
Objective-CCallJavaScriptOnly APIs implemented by the layer can get the returned value.
- Use
callbackRelatively troublesome
- You must
JavaScriptOn your own
IOS 7 +
IOS7 introducedJavaScriptCoreYesJavaScriptAndObjective-CInteroperability.
Objective-CAvailableJSContextOfevalueScript()Method callJavaScriptMethod 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()"];
ImplementJSExportThe object of the Protocol is directly assignedJSContextThe 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 EnvironmentJavaScriptCallObjective-CApi
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);});
JavaScriptCoreVarious 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,JavaScriptCoreThe best communication performance.
Compatibility
The compatibility of various communication methods is as follows (+Supported,XNot 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,WKWebViewNot SupportedJavaScriptCoreBut the message handler method isJavaScriptAndObjective-CCommunication.
InObjective-CUsed inWKWebViewThe following method is called:JavaScript:
- (void)evaluateJavaScript:(NSString *)javaScriptString completionHandler:(void (^)(id, NSError *))completionHandler
IfJavaScriptCode error.completionHandlerProcessing.
InObjective-CTo register message handler:
// WKScriptMessageHandler protocol
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{ NSLog(@"Message: %@", message.body);}[userContentController addScriptMessageHandler:handler name:@"myName"];
InJavaScriptSend 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