Communication between JavaScript and Objective-C in UIWebView, uiwebview

Source: Internet
Author: User

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:

  1. The return value type can only be a string type.
    • Objective-CDeserialization of string results is required
    • JavaScriptSerialization of results may be required
  2. CallJavaScriptIt 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: Modifywindow.location.hrefReplace it with a mergedURLFor exampleasync://method:args
  • Location. hash: Modifywindow.location.hash
  • <a>Click: Create<a>Element, value assignmenthrefAnd call itsclick()Method
  • Iframe. src: CreateiframeElement, value assignmentsrcAttribute
  • XHR sync/async: CreateXMLHttpRequestObject,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:

  1. The entire process is asynchronous and cannot be synchronized.
  2. InJavaScriptCan not directly obtain the returned value of Objective-C Processing
    • YesObjective-CCallJavaScriptOnly APIs implemented by the layer can get the returned value.
  3. UsecallbackRelatively troublesome
    • You mustJavaScriptOn 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
  1. Http://blog.persistent.info/2013/10/a-faster-uiwebview-communication.html
  2. Https://github.com/mihaip/web-experiments/pull/1
  3. Http://www.bignerdranch.com/blog/javascriptcore-example/
  4. Http://oscaraperez.com/blog_assets/JavaScript%20with%20iOS7.pdf
  5. Http://blog.impathic.com/post/64171814244/true-javascript-uiwebview-integration-in-ios7

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.