Objective-c the things that interact with JavaScript

Source: Internet
Author: User
Tags call back string format



Recently, the company's operations to engage in a blind activity, its activities to provide data support services, the Web front-end in the public account as the main operating positions, and iOS, Android to provide the corresponding portals and pages to match. An activity that uses the various end of the program ape. And in the face of technology is mainly related to Web-side and server-side interaction, web front-end and iOS, Android interaction. I as an IOS developer, today chat about the Web, IOS, Android three-terminal interaction, in fact, the white point is the method of mutual invocation. The main explanation here is iOS. Android will slightly mention it for reference only.



The logical diagram of this article






Figure 0-0 The logical diagram of this article






Overview



iOS native Apps and Web pages interact roughly in these ways iOS7 after the JavaScriptCore, intercept protocol, third-party framework Webviewjavascriptbridge, IOS8 after the wkwebview here mainly to explain the JavaScriptCore and interception protocol two ways. Webviewjavascriptbridge is an encapsulation based on the interception protocol. The study cost is relatively javascriptcore higher, the use also is inferior javascriptcore convenient This article does not narrate. Wkwebview is iOS8 after the launch, has not become mainstream use, so this article does not do a detailed description.



Objective-c executing javascript code





Related methods


// Method of UIWebView
-(nullable NSString *) stringByEvaluatingJavaScriptFromString: (NSString *) script;
 
// The method of JSContext in JavaScriptCore
-(JSValue *) evaluateScript: (NSString *) script;
-(JSValue *) evaluateScript: (NSString *) script withSourceURL: (NSURL *) sourceURL
Related applications

It is not necessary to use these methods to execute a large section of JavaScript code, but some small scenes are more convenient and practical to use. Here are two examples for reference:

// Get the title of the current page
NSString * title = [webview stringByEvaluatingJavaScriptFromString: @ "document.title"];
 
// Get the url of the current page
NSString * url = [webview stringByEvaluatingJavaScriptFromString: @ "document.location.href"];
 

JavaScriptCore

After iOS7, Apple introduced the JavaScriptCore framework, which makes it very convenient for web pages to interact with local native applications. Moreover, using this framework can make Android and iOS relatively unified. The web front end writes a set of code to adapt to the two Platform, thereby reducing the workload of the web front end.

web front end

In the three-terminal interaction, the web front-end is more powerful. All values passing and method names are defined by the web front-end developers, and the other two ends are adapted. Here we take the camera and sharing as an example to explain in detail. The test webpage code is named test.html, and the code content is as follows:

test.html code content (due to recognition problems, the angle brackets in the code were replaced with square brackets)

[! DOCTYPE html]
[html]
[head]
    [meta charset = "UTF-8"]
[/ head]
[body]
    [div style = "margin-top: 100px"]
        [h1> The things that Objective-C interacts with JavaScript [/ h1]
        [input type = "button" value = "CallCamera" onclick = "Toyun.callCamera ()"]
    [/ div]
    [div]
        [input type = "button" value = "Share" onclick = "callShare ()"]
    [/ div]
     
[script]
    var callShare = function () {
        var shareInfo = JSON.stringify ({"title": "title", "desc": "content", "shareUrl": "http://www.jianshu.com/p/f896d73c670a",
        "shareIco": "http://upload-images.jianshu.io/upload_images/1192353-fd26211d54aea8a9.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"});
        Toyun.share (shareInfo);
    }
     
    var picCallback = function (photos) {
        alert (photos);
    }
     
    var shareCallback = function () {
        alert (‘success’);
    }
[/ script]
[/ body]
[/ html]
test.html code explanation

 

Maybe some students are not familiar with some knowledge of the web front-end, explain the code a little, first say that Toyun is an object to be injected locally on both sides of iOS and Android [refer to the iOS code below to understand it] A bridge between native applications and web pages. Two button names are defined on the page as CallCamera and Share. Clicking CallCamera will call the local application method through the bridge of Toyun-(void) callCamera, without passing parameters; and clicking Share will first call the JavaScript method in this file callShare here to convert the content format to be shared into JSON string format (do this In order to adapt to Android, iOS can directly accept JSON objects) and then call the native application through the bridge of Toyun-(void) share: (NSString *) shareInfo method. This has a parameter, and the parameter is shareInfo. The following two methods are callback methods after the native method is called. Among them, picCallback is a callback method that successfully obtains the picture, and returns the photos obtained; shareCallback is a callback method that shares successfully.

iOS

The iOS side writes code according to the method name defined by the front end, but sometimes the web front end will let us define it, but after we have defined it, he will modify it, which will be annoying at this time. Therefore, when encountering three-terminal interaction, it is best to let the web front-end define the method name. IOS and Android write code based on the web-front definition. The method of calling a native application in a web page in JavaScriptCore can use Delegate or Block. This article explains by Delegate.

Classes and protocols in JavaScriptCore:

JSContext: Provide the context in which JavaScript runs

JSValue: A bridge between JavaScript and Objective-C data and methods

JSManagedValue: class for managing data and methods

JSVirtualMachine: Processing thread related, less used

JSExport: This is a protocol. If the protocol is used to interact, the protocol you define must comply with this protocol.

Code in ViewController

#import "ViewController.h"
#import [JavaScriptCore / JavaScriptCore.h] (angle brackets here)
 
@protocol JSObjcDelegate [JSExport] (here angle brackets)
 
-(void) callCamera;
-(void) share: (NSString *) shareString;
 
@end
 
@interface ViewController () [UIWebViewDelegate, JSObjcDelegate] (here are angle brackets)
 
@property (nonatomic, strong) JSContext * jsContext;
@property (weak, nonatomic) IBOutlet UIWebView * webView;
 
@end
 
@implementation ViewController
 
#pragma mark-Life Circle
 
-(void) viewDidLoad {
    [super viewDidLoad];
     
    NSURL * url = [[NSBundle mainBundle] URLForResource: @ "test" withExtension: @ "html"];
    [self.webView loadRequest: [[NSURLRequest alloc] initWithURL: url]];
}
 
#pragma mark-UIWebViewDelegate
 
-(void) webViewDidFinishLoad: (UIWebView *) webView {
    self.jsContext = [webView valueForKeyPath: @ "documentView.webView.mainFrame.javaScriptContext"];
    self.jsContext [@ "Toyun"] = self;
    self.jsContext.exceptionHandler = ^ (JSContext * context, JSValue * exceptionValue) {
        context.exception = exceptionValue;
        NSLog (@ "Exception information:% @", exceptionValue);
    };
}
 
#pragma mark-JSObjcDelegate
 
-(void) callCamera {
    NSLog (@ "callCamera");
    // After getting the photo, call the js method picCallback to transfer the image
    JSValue * picCallback = self.jsContext [@ "picCallback"];
    [picCallback callWithArguments: @ [@ "photos"]];
}
 
-(void) share: (NSString *) shareString {
    NSLog (@ "share:% @", shareString);
    // shareCallback method for successful callback js
    JSValue * shareCallback = self.jsContext [@ "shareCallback"];
    [shareCallback callWithArguments: nil];
}
 
@end
Explanation of code in ViewController

Customize the JSObjcDelegate protocol, and this protocol must comply with the JSExport protocol. The method in the custom protocol is the method exposed to the web page. When the webView finishes loading, get the context in which JavaScript runs, and then inject the bridge object named Toyun. The host object is self, which is the controller. The controller complies with this custom protocol to implement the corresponding method in the protocol. After JavaStript calls the method of the local application and finishes the corresponding thing, it also calls back the corresponding method in JavaStript, thus realizing the communication between the web page and the local application.

Use of JavaScriptCore

JavaStript calls the local method to execute in the child thread. Here we need to consider switching between threads according to the actual situation. When calling back the JavaScript method, it is best to execute the JavaStript method in the thread that just started calling this method. The code, I didn't notice it in actual use, I was miserable. What is too much to say, see the following code to explain:

// Assuming that this method is executed in a sub-thread, the thread name is sub-thread
-(void) callCamera {
    // This sentence is assumed to be executed in the main thread, the thread name main-thread
    NSLog (@ "callCamera");
       
    // The following two lines of code are best executed in sub-thread sub-thread.
    JSValue * picCallback = self.jsContext [@ "picCallback"];
    [picCallback callWithArguments: @ [@ "photos"]];
}
running result

Running effect shown in 3-1

Figure 3-1 Running effect

 

 

 

 

Intercept protocol

The interception protocol is suitable for some relatively simple cases. No framework is needed, only the web front-end needs to cooperate. However, it may be inconvenient in which method to call and when passing the value, and the JavaScript method cannot be called back after the call.

web front end

The code in test.html (for recognition problems, the angle brackets in the code were replaced with square brackets)

[! DOCTYPE html]
[html]
[head]
    [meta charset = "UTF-8"]
[/ head]
[body]
    [div]
        [input type = "button" value = "CallCamera" onclick = "callCamera ()"]
    [/ div]
     
[script]
    function callCamera () {
        window.location.href = ‘toyun: // callCamera’;
    }
[/ script]
[/ body]
[/ html]
Code explanation in test.html

This code is very simple compared to the above test code. It also has a button named CallCamera, which calls its own callCamera method after clicking. Window.location.href is here to change the direction of the main window and immediately issue a link as Toyun: // callCamera request, and the parameters that you want to pass to the native application can also be included in this request, and in the iOS method we have to intercept this request and judge what JavaStript wants to do based on the content of the request, so as to achieve Interaction between web pages and local applications.

iOS

iOS corresponding code

-(BOOL) webView: (UIWebView *) webView shouldStartLoadWithRequest: (NSURLRequest *) request navigationType: (UIWebViewNavigationType) navigationType
{
    NSString * url = request.URL.absoluteString;
    if ([url rangeOfString: @ "toyun: //"] .location! = NSNotFound) {
        // The protocol header of the url is Toyun
        NSLog (@ "callCamera");
        return NO;
    }
    return YES;
}
Explanation of the code corresponding to iOS

In the webView proxy method, intercept the custom protocol Toyun: // If it is this protocol, judge what JavaStript wants to do based on this, and call the method of the native application. These are agreed in advance, and this link is blocked. Jump.

to sum up

With the increasingly powerful configuration of mobile phone hardware and the rise of HTML5, an App can be written by a web page. Some applications have done so now, I have met, such as Ancient Poetry and Literature Network. Although relatively small, the interaction between web pages and local applications will be encountered whether iOS or Android. I still recommend JavaScriptCore for iOS, so the three ends can be relatively unified, and it is easier to write. Over time, WKWebView introduced by iOS8 will gradually become mainstream, and this function is more powerful. The interception protocol can only be used in some simple cases. It is more troublesome to pass parameters to each other in complex situations. And this method cannot call back JavaScript. Students who really like the interception protocol can study WebViewJavaScriptBridge. Library. For Android, I just know a little about the fur, so I do n’t want to do anything. For some Android developers, you can read the test.html page in the first paragraph to fully adapt to Android.

reference

iOS and JS interactive combat articles (ObjC version)

Things that Objective-C interacts with JavaScript

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.