JS and objective-c Interaction-standby

Source: Internet
Author: User

When writing JavaScript, you can use an object called window, like when we want to jump from the current page to another page, we will change the location of the window.location.href, in our OBJECTIVE-C program code, If we can get the specified WebView indicator, we can get the window object that appears in JavaScript, that is, [WebView Windowscriptobject].

This object is the bridge between JS in WebView and our OBJECTIVE-C program-window object can get all the JS functions and objects inside the page, and if we set a Objective-c object to Windowscriptobject Value,js can also invoke the method of the Objective-c object. Therefore, we can in the OBJECTIVE-C program requires WebView to execute a section of JS, can also be used in turn to JS invoke a section of the function of OBJ C.

※ with objective-c Get and set JavaScript Object

To get the JavaScript object in the Web page from Objective-c, that is, make some KVC calls to Windowscriptobject, like Valueforkey: With Valueforkeypath:. If we are in JS and want to know the current page location, we will write:

var location = Window.location.href;

This can be called with objective-c:

NSString *location = [[WebView windowscriptobject] valueforkeypath:@ "Location.href"];

If we want to set window.location.href, ask to open another page, in JS:

window.location.href = ' http://spring-studio.net ';

In Objective-c:

[[WebView Windowscriptobject] setvalue:@ "http://spring-studio.net" forkeypath:@ "Location.href"];

Because of the different language characteristics of objective-c and JS itself, the difference between the two languages can be seen by passing things between them:

    • JS is OO, but there is no class, so the JS object to the OBJ C program inside, in addition to the basic string will be converted to NSString, the basic number will be turned into nsnumber, such as an Array and other objects, in Objective-c, are WEBSCR Iptobject this Class. It means that the JS Array will not help you convert to Nsarray.
    • From JS inside an empty object to the OBJECTIVE-C program, with not objective-c in the original expression "no things" way, such as NULL, nil, NSNull, etc., but the exclusive WebKit use of webundefined.

So, if we want to see something in a JS Array, we first get the value of the object called length, and then use Webscriptvalueatindex: To see the content at the index position.

If we write this in JS:

var Jsarray = {' zonble ', ' dot ', ' net '};

for (var i = 0; i < jsarray.length; i++) {

Console.log (Jsarray[i]);

}

It's going to be like this in objective-c:

Webscriptobject *obj = (Webscriptobject *) Jsarray;

Nsuinteger count = [[obj valueforkey:@ "Length"] integervalue];

Nsmutablearray *a = [Nsmutablearray array];

for (Nsuinteger i = 0; i < count; i++) {

NSString *item = [obj webscriptvalueatindex:i];

NSLog (@ "item:%@", item);

}

※ with Objective C called JavaScript function

There are several ways to invoke JS function in a Web page with Objective-c. The first is to write a section directly with you in the Web page will be written in the same program, called Windowscriptobject with Evaluatewebscript: Execute.

For example, we want to create a new JS function in the Web page with the following content:

function x (x) {

return x + 1;

}

So it can be written in objective-c;

[[WebView Windowscriptobject] evaluatewebscript:@ "function x (x) {return x + 1;}"];

Next we can call Window.x ():

NSNumber *result = [[WebView windowscriptobject] evaluatewebscript:@ "x (1)"];

NSLog (@ "result:%d", [result IntegerValue]); Returns 2

Because in JS, each funciton is actually the object, so we can also directly get window.x call this object to execute itself.

In JS If you write this:

Window.x.call (window.x, 1);

This is the case in Objective-c:

Webscriptobject *x = [[WebView windowscriptobject] valueforkey:@ "x"];

NSNumber *result = [x callwebscriptmethod:@ "Call" Witharguments:[nsarray arraywithobjects:x, [NSNumbernumberWithInt:1 ], Nil]];

This lets some webscriptobject own implementation of their own writing, in fact, the comparison will not be used from the OBJECTIVE-C call JS this end, but the next will be mentioned, by JS call objective-c, because so JS can put a callback func tion sent to the OBJECTIVE-C program.

If we are doing a Web page and we just want to update a chunk of the page, we will use the AJAX technique to send a request to the server only for the data needed for that chunk, and request a callback function when the request is complete. Update the display of this chunk. Call Objective-c from JS can also do similar things, if the OBJECTIVE-C program takes a certain amount of time to calculate, or we may be in the Objective-c crawl network data, we can send a callback function to In the OBJECTIVE-C program, the OBJECTIVE-C program is required to perform this callback function after the work is done.

DOM

In WebKit, all DOM objects inherit from Domobject,domobject and inherit from Webscriptobject, so after we get a DOM object, we can also ask the DOM object to execute J from the OBJECTIVE-C program. S program.

If we have an ID called "#s" text input box in our Web page, and we want the focus of the keyboard input now on this input box, this will be written in JS:

Document.queryselector (' #s '). focus ();

In the objective-c:

DOMDocument *document = [[WebView mainFrame] DOMDocument];

[Document Queryselector:@ "#s"] callwebscriptmethod:@ "focus" witharguments:nil];

※ with JavaScript Access Objective C of the Value

To allow the JS program in the Web page to invoke the Objective-c object, the method is to register a Objective-c object as a property of the Window object in JS. After that, JS can also call this object's method, you can also obtain the object's various value, as long as the KVC can be obtained value, such as NSString, NSNumber, NSDate, Nsarray, Nsdictionary, Nsvalue ... such as JS transmission Array to objective-c, but also need to do some special processing to become Nsarray, from OBJ C to a nsarray to JS, will automatically become JS Array.

The first thing to note is the time to register the Objective-c object with the Window object, because each time the page is re-loaded, the contents of the Window object will be changed-after all, each page will have a different JS program, so we need to do it at the right time. We will first specify WebView's frame loading delegate (with Setframeloaddelegate:) and implement Webview:didclearwindowobject:forframe:,webview This section of the program is called whenever Windowscriptobject is updated.

If we now want to let JS in the Web page can use the current controller object, this will write:

-(void) WebView: (WebView *) sender Didclearwindowobject: (Webscriptobject *) WindowObject forframe: (Webframe *) frame

{

[WindowObject setvalue:self forkey:@ "Controller"];

}

As a result, we can call our Objective-c object whenever Window.controller is called. If we have these member variables in our objective-c Class:

@interface Mycontroller:nsobject

{

Iboutlet WebView *webview;

Iboutlet Nswindow *window;

NSString *stringvalue;

Nsinteger Numbervalue;

Nsarray *arrayvalue;

NSDate *datevalue;

Nsdictionary *dictvalue;

Nsrect Framevalue;

}

@end

Specify Value:

StringValue = @ "string";

Numbervalue = 24;

Arrayvalue = [[Nsarray arraywithobjects:@ "text", [nsnumbernumberwithint:30], nil] retain];

DateValue = [[NSDate date] retain];

Dictvalue = [[Nsdictionary dictionarywithobjectsandkeys:@ "value1", @ "Key1", @ "value2", @ "Key2", @ "Value3", @ "Key3", nil ] retain];

Framevalue = [window frame];

Read and read with JS:

var c = Window.controller;

var main = document.getElementById (' main ');

var HTML = ';

if (c) {

HTML + = ' <p> ' + c.stringvalue + ' <p> ';

HTML + = ' <p> ' + c.numbervalue + ' <p> ';

HTML + = ' <p> ' + c.arrayvalue + ' <p> ';

HTML + = ' <p> ' + c.datevalue + ' <p> ';

HTML + = ' <p> ' + c.dictvalue + ' <p> ';

HTML + = ' <p> ' + c.framevalue + ' <p> ';

main.innerhtml = HTML;

}

The results are as follows:

String text,30 2010-09-09 00:01:04 +0800 {key1 = value1; key2 = value2; Key3 = Value3;} Nsrect: {{275, 72}, {570, 657}}

However, if you look at the above example, directly do, should not directly succeed in the correct results, but will get a bunch of undefined, because the Objective-c object Value preset is protected, will not let JS directly access. To allow JS to access the Value of the Objective-c object, you need to operate +iskeyexcludedfromwebscript: for the incoming key one by one processing, if we want JS to access this key, the return NO:

+ (BOOL) Iskeyexcludedfromwebscript: (const char *) name

{

if (!strcmp (name, "StringValue")) {

return NO;

}

return YES;

}

In addition to reading the value of the Objective-c object, you can also set value, which is equivalent to using Setvalue:forkey in Objective-c: If in the JS program above, we want to modify the StringValue, call directly C.stringvalue = ' new value '. As mentioned earlier, the JS object passed to objective-c here, except for strings and numbers, class is Webscriptobject, empty object is webundefined.

with JavaScript called Objective C Method

Objective-c syntax inherits from Smalltalk,objective-c's selector, which is quite different from JS's function syntax. WebKit preset is, if we want to call Objective-c selector in JS, is to put all the parameters to the back of the pendulum, and all the colon to the bottom line, and the original selector if there is a bottom line, but also to deal with.

If our controller object has a method, it is written in objective-c:

-(void) SetA: (ID) a B: (ID) b C: (ID) C;

This is called in JS:

Controller.seta_b_c_ (' A ', ' B ', ' C ');

It's really ugly. So WebKit provides a way for us to turn some objective-c selector into a better-looking JS function. We want to do webscriptnameforselector:

+ (NSString *) Webscriptnameforselector: (SEL) Selector

{

if (selector = = @selector (seta:b:c:)) {

return @ "SETABC";

}

return nil;

}

You can call this later:

CONTROLLER.SETABC (' A ', ' B ', ' C ');

We can also decide which selector can be used for JS and which to protect, and the method is to implement Isselectorexcludedfromwebscript:. And we can change the name of a objective-c selector in JS, we can also change the key of a value, the method is to implement the Webscriptnameforkey:.

Here are a few things to look out for:

Call the property of Objective C 2.0 with JavaScript

In the above, we use JS to call Window.controller.stringValue, and set the value inside, the side is much like we use the OBJECTIVE-C 2.0 syntax, but actually do is not the same thing. Call Controller.stringvalue with JS, corresponding to the OBJECTIVE-C syntax is [controller valueforkey:@ "StringValue"], instead of calling the Objective-c object's Property

If our Objective-c object has a property called StringValue, we know that the Objective-c property will actually be at compile time, become Getter/setter method, in JS, we should call Controller.stringvalue () and Controller.setstringvalue_ ().

In Javascript, Function is the property of an object

JS function is an object, when a Objective-c object method appears in the JS, this method in JS, can more or less as object processing. We have a setabc on it, and we can try to pour it out and see:

Console.log (CONTROLLER.SETABC);

We can see from the results:

function Setabc () {[native code]}

This function is native code. Because it is native code, we cannot invoke call or apply on this function.

In addition, after registering our Objective-c object as Window.controller, we will also want to let the controller become a function to execute, such as Call Window.controller (); We just want to produce a function that allows JS to call, not the whole object into JS. As long as we are doing invokedefaultmethodwitharguments in the Objective-c object, we can return the result we want when we call Window.controller ().

Now we can do a comprehensive exercise. As mentioned earlier, because we can put the JS object to webscriptobject this class into the OBJ C program, OBJECTIVE-C program can also require the execution of webscriptobject function. If we want to throw a and B two numbers into the OBJECTIVE-C program to do an addition, and then appear on the Web page, so we wrote a objective-c method:

-(void) Numberwitha: (ID) a PLUSB: (ID) b callback: (ID) callback

{

Nsinteger result = [a integervalue] + [b integervalue];

[Callback callwebscriptmethod:@ "Call" Witharguments:[nsarrayarraywithobjects:callback, [NSNumber NumberWithInteger : Result],nil]];

}

JS inside can call:

Window.controller.numberWithA_plusB_callback_ (1, 2,function (result) {

var main = document.getElementById (' main ');

Main.innertext = result;

});

on other platforms WebKit usage of

In addition to Mac OS X,webkit has been slowly ported to other operating systems and frameworks in recent years, there are more or less Native APIs that require WebView to execute JS, as well as a mechanism to invoke Native APIs from JS.

Compared to Mac OS X, there is much less public API for UIWebView on IOS. Want to let UIWebView execute a section of JS, can call Stringbyevaluatingjavascriptfromstring:, will only return the string result, so can do things become limited, usually take to get like Window.title this information. On IOS, we have no way to turn a Objective-c object into a JS object, so, in the Web page triggered some events, want to notify objective-c this end, often choose to use such customized URL scheme like "zonble://".

ChromeOS is completely WebKit as a user interface, but there's no way we can write the desktop or mobile application we're talking about here on Chomeos, so it's not in our discussion. (Straight turnout problem, ChromeOS is designed to give Netbook use of the operating system, but like Toshiba have been using Android, make a smaller than Netbook Smartbook, and the application more, ChromeOS products do, it is really like G Oogle took out two sets of things, himself to fight with himself).

Android's WebView object provides a method called Addjavascriptinterface () that can be used to register a Java object as a property of a JS window object, allowing JS to invoke a Java object. However, when invoking the Java object, only can pass the simple text, the number, the complex JS object can not be able. And on the Android want to WebView execute a section of JS, in the file did not see the relevant information, the network above find the saying is, can through the Loadurl (), a section of JS with the form of Bookmarklet passed in.

In the Qtwebkit, you can call the Qwebframe addtojavascriptwindowobject, a qobject exposed in the JS environment, I do not know what JS can be transmitted to qobject inside just. DOM objects inside the page can also be obtained in Qtwebkit (qwebelement
, qwebelementcollection), we can call Evaluatejavascript on Qwebframe and these DOM objects to execute Javascript.

GTK, because it is the C API, so between the application and JS, not through the operation of packaged objects, but instead of invoking the WebKit JavaScript Engine C API.

JavaScriptCore Framework

On Mac OS X, we can also request WebView to execute Javascript through the C API. The first thing to do is import. If we want to simply change the window.location.href:

Jsglobalcontextref globalcontext = [[WebView mainFrame] globalcontext];

Jsvalueref exception = NULL;

Jsstringref script = jsstringcreatewithutf8cstring ("window.location.href= ' http://spring-studio.net '");

Jsevaluatescript (globalcontext, script, null, NULL, 0, &exception);

Jsstringrelease (script);

Thank the great God for sharing

If we want to get JS inside WebView, we can call our C Function:

-(void) WebView: (WebView *) sender Didclearwindowobject: (Webscriptobject *) WindowObject forframe: (Webframe *) frame

{

Jsglobalcontextref Globalcontext = [frame Globalcontext];

Jsstringref name = jsstringcreatewithutf8cstring ("MyFunc");

Jsobjectref obj = jsobjectmakefunctionwithcallback (globalcontext, Name, (Jsobjectcallasfunctioncallback) myFunc);

Jsobjectsetproperty (Globalcontext, [WindowObject Jsobject], name, obj, 0, NULL);

Jsstringrelease (name);

}

So, as long as JS call Window.myfunc (), you can get the results of the myFunc in this C function:

Jsvalueref MyFunc (jscontextref ctx, jsobjectref function, Jsobjectref thisobject, size_t argumentcount, const JSVALUEREF Arguments[], jsvalueref* exception)

{

Return Jsvaluemakenumber (CTX, 42);

}

JS and objective-c Interaction-standby

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.