Interactive summary of iOS and JS development

Source: Internet
Author: User
Tags button type

Hybrid.jpg

Objective

How JS in a Web page interacts with iOS Native is a skill that every iOS ape must master. And when it comes to Native and JS interaction, you have to mention a mouth Hybrid.

Hybrid's translation is not very civilized (wipe the sweat, do not know why many translation software will be translated as "hybrid", but I prefer to translate it into "mixed, half-blood"), Hybrid Mobile App I understand it as through WEB network technology (such as HTML,CSS and JavaScript) hybrid mobile applications that are combined with Native.

So let's see what the pros and cons of Hybrid compare Native:

Hybrid_vs_native.jpg

Because the flexibility of Hybrid (changing Web pages does not have to be re-issued) and versatility (a H5 to play across all platforms) plus a low threshold (front apes can be painless to get started), it is possible to use the web in a non-core functional module by Hybrid way to achieve the possibility from all aspects will be better than Nati Ve. Native can provide powerful support for JS on the core function and the device hardware call.

Index

    • A brief history of Hybrid development

    • JavaScriptCore Introduction

    • How IOS Native interacts with JS

    • The unique method of Wkwebview and JS interaction

    • JS via Native call IOS device webcam Demo

    • Summarize

A brief history of Hybrid development

The following is a brief description of Hybrid's history:

1.H5 Release

Html5.png

HTML5 was officially released in September 2014, and one of the biggest changes in this release was "upgrading from a previous subset of XML to a separate collection."

2.H5 infiltrate Mobile App Development

There is a WebView component in Native APP development (Webview,ios has UIWebView and Wkwebview in Android) and this component can load Html files.

Before H5 big line, WebView loaded Web page is very monotonous (because only some static resources can be loaded), since the H5 fire, the front-end ape developed H5 page in the WebView performance is very good, so that the H5 development slowly penetrated into the Mobile App development.

3.Hybrid status

Although there have been RN and Weex these use JS write Native App technology, but Hybrid still not be eliminated, most of the market application has introduced the Web page to a different degree.

JavaScriptCore

JavaScriptCore this library, which Apple added to the standard library after iOS 7, has an epoch-making impact on the iOS Native and JS interaction calls.

JavaScriptCore is roughly comprised of 4 classes and 1 protocols:

Javascriptcore_framework.jpg

    • Jscontext is the JS execution context, which you can interpret as the JS running environment.

    • Jsvalue is a reference to JavaScript values, and any value in JS can be packaged as a jsvalue.

    • Jsmanagedvalue is the packaging of Jsvalue, added "conditional retain".

    • Jsvirtualmachine represents an isolated environment for JavaScript execution.

There are also Jsexport protocols:

Implements a protocol that exports the Objective-c class and its instance methods, class methods, and properties to JavaScript code.

The jscontext,jsvalue,jsmanagedvalue here is relatively good understanding, the following we put Jsvirtualmachine to illustrate:

The usage of jsvirtualmachine and its relationship with Jscontext

Jsvirtualmachine.jpg

An introduction to the official documentation:

The Jsvirtualmachine instance represents an isolated environment for JavaScript execution. You use this class for two main purposes: to support concurrent JavaScript execution, and to manage the memory of objects bridged between JavaScript and objective-c or Swift.

With regard to the use of jsvirtualmachine, in general we do not have to manually create the Jsvirtualmachine. Because when we get Jscontext, the acquired Jscontext belongs to a jsvirtualmachine.

Each JavaScript context (Jscontext object) belongs to a jsvirtualmachine. Each jsvirtualmachine can contain multiple contexts, allowing values to be passed between contexts (Jsvalue objects). However, each jsvirtualmachine is different, that is, we cannot pass the value created in one jsvirtualmachine to the context in another jsvirtualmachine.

The JavaScriptCore API is thread-safe-for example, we can create Jsvalue objects from any thread or run JS scripts-but all other threads that try to use the same jsvirtualmachine will be blocked. To run JavaScript scripts concurrently (concurrently) on multiple threads, use a separate jsvirtualmachine instance for each thread.

Conversion tables for Jsvalue and JavaScript

IOS Native and JS interaction

For IOS Native and JS interaction we start with the direction of the call in two ways:

    • JS Call Native

    • Native Call JS

Call-eachother.jpg

JS Call Native

In fact, JS call IOS Native is also divided into two ways:

    • False Request method

    • JavaScriptCore method

False Request method

Principle: In fact, this way is the use of WebView proxy method, in the WebView to start the request to intercept the request, judge whether the request is a good deal of false request. If it is a false request is that JS want to follow the convention call our Native method, according to the Convention to execute our Native code is good.

UIWebView

The UIWebView agent has a function for intercepting the request, and it is good to make a judgment inside:

-(BOOL) WebView: (UIWebView *) WebView shouldstartloadwithrequest: (nsurlrequest *) Request Navigationtype: ( Uiwebviewnavigationtype) Navigationtype {

Nsurl *url = Request. URL;

Comparison with well-appointed function masterpieces

if ([[URL scheme] isequaltostring:@ "Your_func_name"]) {

Just do it

}

}

Wkwebview

Wkwebview has two agents, one is wknavigationdelegate and the other is wkuidelegate. Wkuidelegate We will talk about this in the following chapters, here we need to set up and implement its Wknavigationdelegate method:

-(void) WebView: (Wkwebview *) WebView decidepolicyfornavigationaction: (wknavigationaction *) navigationaction Decisionhandler: (void (^) (wknavigationactionpolicy)) Decisionhandler {

Nsurl *url = NavigationAction.request.URL;

Comparison with well-appointed function masterpieces

if ([[URL scheme] isequaltostring:@ "Your_func_name"]) {

Just do it

Decisionhandler (Wknavigationactionpolicycancel);

Return

}

Decisionhandler (Wknavigationactionpolicyallow);

}

Note:decisionhandler is the code block to invoke when your application decides whether to allow or cancel navigation. The code block uses a single parameter, which must be one of the constants of the enumeration type Wknavigationactionpolicy. If you do not call Decisionhandler it will cause crash.

Add the JS code here:

function callnative () {

Loadurl ("your_func_name://xxx");

}

Then take a button tag and use it for a moment:

<button type= "button" onclick= "Callnative ()" >call native!</button>

JavaScriptCore method

IOS 7 has javascriptcore specifically designed to do Native and JS interactions. We can get jscontext after WebView finishes loading, and then use Jscontext to refer to the object in JS to interpret or respond to it using the Native code:

First introduce the JavaScriptCore library

#import <JavaScriptCore/JavaScriptCore.h>

And then UIWebView to finish loading the proxy method

-(void) Webviewdidfinishload: (UIWebView *) WebView {

Get JS Context

Jscontext = [WebView valueforkeypath:@ "DocumentView.webView.mainFrame.javaScriptContext"];

To make a reference, the elements in the JS reference to explain, such as the method can be interpreted as Block, the object can also point to OC Native object Oh

jscontext[@ "iosdelegate"] = self;

jscontext[@ "Yourfuncname"] = ^ (id parameter) {

Note that the thread here is the Web processing thread by default, and if the main thread is involved, you need to go to the main thread manually

Dispatch_async (Dispatch_get_main_queue (), ^{

Your code

});

}

}

And JS side of the code is simpler, simply declare a non-explanatory function (the name of the contract), used to give Native reference:

var parameter = xxx;

Yourfuncname (parameter);

IOS Native Call JS

The implementation of the IOS Native call JS is also divided by JavaScriptCore:

    • WebView directly into JS and execute

    • JavaScriptCore method

WebView directly into JS and execute

On the IOS platform, WebView has an API to inject and execute JS.

UIWebView

UIWebView has the method of directly injecting JS:

NSString *jsstr = [NSString stringwithformat:@ "Showalert ('%@ ')", @ "alert msg"];

[_webview STRINGBYEVALUATINGJAVASCRIPTFROMSTRING:JSSTR];

Note: This method returns the result of running JS (nullable NSString *), which is a synchronous method that blocks the current thread! Although this method is not deprecated, it is a best practice to use the evaluateJavaScript:completionHandler:method of the Wkwebview class.

Official documents:

The Stringbyevaluatingjavascriptfromstring:method waits synchronously for JavaScript evaluation to complete. If you load Web content whose JavaScript code that has not vetted, the invoking this method could the hang your app. Best Practice is to adopt the Wkwebview class and use its evaluateJavaScript:completionHandler:method instead.

Wkwebview

The method that differs from Uiwebview,wkwebview injection and execution of JS does not block the current thread. Because the JS code in the Web content that WebView loads is not necessarily verified, the blocking thread may suspend the APP.

NSString *jsstr = [NSString stringwithformat:@ "setlocation ('%@ ')", @ "nan gu gong xiang hannaford hu Tong xx, Dongcheng District, Peking City"];

[_webview evaluatejavascript:jsstr completionhandler:^ (id _nullable result, nserror * _nullable error) {

NSLog (@ "%@----%@", result, error);

}];

Note: The method does not block the thread, and its callback code block always runs in the main thread.

Official documents:

Evaluates a JavaScript string.

The method sends the result of the script evaluation (or an error) to the completion handler. The completion handler always runs on the main thread.

JavaScriptCore method

The above simply mentions the Jsvalue class provided by the JavaScriptCore Library, which provides an introduction to Jsvalue in the official documentation:

A Jsvalue instance is a reference to a JavaScript value. You can use the Jsvalue class to convert basic values (such as numbers and strings) between JavaScript and Objective-c or Swift to pass data between native code and JavaScript code.

But you also saw the OC and JS data type conversion tables that I posted above, which are not limited to the basic values stated in the official documentation. If you are unfamiliar with JS, I will explain why Jsvalue can also point to the object and function JS, because the JS language does not distinguish between basic values and objects and functions, in JS "Everything is the object".

Okay, here's the direct show Code:

First introduce the JavaScriptCore library

#import <JavaScriptCore/JavaScriptCore.h>

Get the JS context first

Self.jscontext = [WebView valueforkeypath:@ "DocumentView.webView.mainFrame.javaScriptContext"];

If the UI action is involved, the tangent back to the main thread calls the Yourfuncname in the JS code, via the array @[parameter] into the parameter

Dispatch_async (Dispatch_get_main_queue (), ^{

Jsvalue *jsvalue = self.jscontext[@ "Yourfuncname"];

[Jsvalue Callwitharguments:@[parameter]];

});

The above code calls the Yourfuncname function in the JS code, and adds @[parameter] as the entry parameter to the function. In order to facilitate reading comprehension, here again paste the JS code:

function Yourfuncname (arguments) {

var result = arguments;

Do the u want to do

}

The unique method of Wkwebview and JS interaction

Wkwebview.jpg

The difference between Wkwebview and UIWebView is not explained in detail in this article, and more information is also available for your own reference. This is about Wkwebview's unique approach when interacting with JS:

    • Wkuidelegate method

    • MessageHandler method

Wkuidelegate method

For Wkwebview mentioned above, in addition to Wknavigationdelegate, it also has a wkuidelegate, what is this wkuidelegate for?

The Wkuidelegate protocol contains functions that are used to listen for Web JS when you want to display alert or confirm. If we load a Web in Wkwebview and want the Web JS alert or confirm to pop up properly, we need to implement the corresponding proxy method.

Note: If the corresponding proxy method is not implemented, WebView will follow the default action to make the behavior.

  • Alert:if implement this method, the Web view would behave as If the user selected the OK button.

  • Confirm:if implement this method, the Web view would behave as If the user selected the Cancel button.

We take the alert example here, and I believe you can extrapolate your readers. Here are the chestnuts in the proxy method for wkuidelegate listening Web to display alert using the Native Uialertcontroller instead of the alert display in JS:

-(void) WebView: (Wkwebview *) WebView runjavascriptalertpanelwithmessage: (NSString *) message initiatedbyframe: ( Wkframeinfo *) frame Completionhandler: (void (^) (void)) Completionhandler {

Use Native's Uialertcontroller pop-up window to display the information JS will prompt

Uialertcontroller *alert = [Uialertcontroller alertcontrollerwithtitle:@ "Reminder" Message:message PreferredStyle: Uialertcontrollerstylealert];

[Alert addaction:[uialertaction actionwithtitle:@ "Know" Style:uialertactionstylecancel handler:^ (UIAlertAction * _ Nonnull action) {

Completionhandler must be called within the function

Completionhandler ();

}]];

[Self Presentviewcontroller:alert animated:yes completion:nil];

}

MessageHandler method

MessageHandler is a Native intercept JS false request after another kind of JS call Native method, the method takes advantage of the new features of Wkwebview implementation. Compared with the method of intercepting false Request, the MessageHandler parameter is more simple and convenient.

What does MessageHandler mean?

The Wkusercontentcontroller class has a method:

-(void) Addscriptmessagehandler: (id <WKScriptMessageHandler>) scriptmessagehandler name: (NSString *) name;

This method is used to add a script processor, can be processed within the processor to the JS script call method, so as to achieve the purpose of JS call Native.

So Wkusercontentcontroller and Wkwebview have a hairy relationship?

In the initialization function of Wkwebview, there is an entry configuration, whose type is wkwebviewconfiguration. Wkwebviewconfiguration contains an attribute Usercontentcontroller, the Usercontentcontroller is an instance of the Wkusercontentcontroller type, We can use this usercontentcontroller to add a different name to the script processor.

Wkusercontentcontroller.jpg

MessageHandler's pit.

So back to-(void) Addscriptmessagehandler:name: Method Above, this method adds a script message handler (the first entry parameter Scriptmessagehandler), and gives the processor a name (the second entry parameter Name). However, this function in use when there is a pit: Scriptmessagehandler into the participants are strongly quoted, then if you wkwebview the current Uiviewcontroller as the first entry, this Viewcontroller Webview.configuration by his own possession. Usercontentcontroller, it will cause a circular reference.

Retaincycle.jpg

We can delete a strong reference to Viewcontroller by using the-(void) Removescriptmessagehandlerforname: method. So in general our code will be added and removed in Viewwillappear and viewwilldisappear MessageHandler:

-(void) Viewwillappear: (BOOL) Animated {

[Super viewwillappear:animated];

[Self.webview.configuration.userContentController addscriptmessagehandler:self name:@ "Yourfuncname"];

}

-(void) Viewwilldisappear: (BOOL) Animated {

[Super viewwilldisappear:animated];

[Self.webview.configuration.userContentController removescriptmessagehandlerforname:@ "Yourfuncname"];

}

Wkscriptmessagehandler protocol

Wkscriptmessagehandler is a script information processor protocol that must be adhered to if you want an object to have script-handling capabilities (such as the self of the above code, WebView, which belongs to Viewcontroller above).

The Wkscriptmessagehandler protocol is very simple inside, there is only one way we have to implement this method (@required):

Wkscriptmessagehandler protocol method, triggering when a script message is received

-(void) Usercontentcontroller: (Wkusercontentcontroller *) Usercontentcontroller didreceivescriptmessage: ( Wkscriptmessage *) Message {

Message has two properties: Name and Body

Message.name can be used to distinguish between the processing to be done

if ([Message.name isequaltostring:@ "Yourfuncname"]) {

Message.body equivalent to JS passed over the parameters

NSLog (@ "JS Call native Success%@", message.body);

}

}

Add the JS code:

<name> Change yourfuncname,<messagebody> for the entry you want

Window.webkit.messagehandlers.<name>.postmessage (<messageBody>)

This article transferred from: HTTP://WWW.JIANSHU.COM/P/5329170BE7B3

Interactive summary of iOS and JS development

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.