JavaScript and objective-c Communication in UIWebView

Source: Internet
Author: User


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:

    1. Return value type can only be string type
      • Objective-CThe string result needs to be deserialized
      • JavaScriptThe result may need to be serialized
    2. 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:

    1. The entire process is asynchronous and cannot be synchronized
    2. 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
    3. 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
    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

JavaScript and objective-c Communication in UIWebView

Related Article

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.