< Previous PageNext Page > Hide TOC

Using Objective-C From JavaScript

The web scripting capabilities of WebKit permit you to access Objective-C properties and call Objective-C methods from the JavaScript scripting environment.

An important but not necessarily obvious fact about this bridge is that it does not allow any JavaScript script to access Objective-C. You cannot access Objective-C properties and methods from a web browser unless a custom plug-in has been installed. The bridge is intended for people using custom plug-ins and JavaScript environments enclosed within WebKit objects (for example, a WebView).

Contents:

How to Use Objective-C in JavaScript
A Sample Objective-C Class


How to Use Objective-C in JavaScript

The WebScripting informal protocol, defined in WebScriptObject.h, defines methods that you can implement in your Objective-C classes to expose their interfaces to a scripting environment such as JavaScript. Methods and properties can both be exposed. To make a method valid for export, you must assure that its return type and all its arguments are Objective-C objects or basic data types like int and float. Structures and non object pointers will not be passed to JavaScript.

Method argument and return types are converted to appropriate types for the scripting environment. For example:

Instances of all other classes are wrapped before being passed to the script, and unwrapped as they return to Objective-C.

A Sample Objective-C Class

Let’s look at a sample class. In this case, we will create an Objective-C address book class and expose it to JavaScript. Let’s start with the class definition:

@interface BasicAddressBook: NSObject {
}
+ (BasicAddressBook *)addressBook;
- (NSString *)nameAtIndex:(int)index;
@end

Now we’ll write the code to publish a BasicAddressBook instance to JavaScript:

BasicAddressBook *littleBlackBook = [BasicAddressBook addressBook];
 
id win = [webView windowScriptObject];
[win setValue:littleBlackBook forKey:@"AddressBook"];

That’s all it takes. You can now access your basic address book from the JavaScript environment and perform actions on it using standard JavaScript functions. Let’s make an example showing how you can use the BasicAddressBook class instance in JavaScript. In this case, we’ll print the name of a person at a certain index in our address book:

function printNameAtIndex(index) {
    var myaddressbook = window.AddressBook;
    var name = myaddressbook.nameAtIndex_(index);
    document.write(name);
}

You may have noticed one oddity in the previous code example. There is an underscore after the JavaScript call to the Objective-C nameAtIndex method. In JavaScript, it is called nameAtIndex_. This is an example of the default method renaming scheme in action.

Unless you implement webScriptNameForSelector to return a custom name, the default construction scheme will be used. It is your responsibility to ensure that the returned name is unique to the script invoking this method. If your implementation of webScriptNameForSelector returns nil or you do not implement it, the default name for the selector will be constructed as follows:

The following table shows example results of the default method name constructor:

Objective-C selector

Default script name for selector

setFlag:

setFlag_

setFlag:forKey:withAttributes:

setFlag_forKey_withAttributes_

propertiesForExample_Object:

propertiesForExample$_Object_

set_$:forKey:withDictionary:

set$_$$_forKey_withDictionary_

Since the default construction for a method name can be confusing depending on its Objective-C name, you would benefit yourself and the users of your class if you implement webScriptNameForSelector and return more human-readable names for your methods.

Getting back to the BasicAddressBook, now we’ll implement webScriptNameForSelector for our nameAtIndex method. In our BasicAddressBook class implementation, we’ll add this:

+ (NSString *) webScriptNameForSelector:(SEL)sel
{
    ...
 
    if (sel == @selector(nameAtIndex:))
            name = @"nameAtIndex";
 
    return name;
}

Now we can change our JavaScript code to reflect our more logical method name:

function printNameAtIndex(index) {
    var myaddressbook = window.AddressBook;
    var name = myaddressbook.nameAtIndex(index);
    document.write(name);
}

For security reasons, no methods or KVC keys are exposed to the JavaScript environment by default. Instead a class must implement these methods:

+ (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector;
+ (BOOL)isKeyExcludedFromWebScript:(const char *)name;

The default is to exclude all selectors and keys. Returning NO for some selectors and key names will expose those selectors or keys to JavaScript.

See WebKit Objective-C Framework Reference for all the information on excluding methods and properties from the JavaScript environment.



< Previous PageNext Page > Hide TOC


© 2004, 2008 Apple Inc. All Rights Reserved. (Last updated: 2008-10-15)


Did this document help you?
Yes: Tell us what works for you.
It’s good, but: Report typos, inaccuracies, and so forth.
It wasn’t helpful: Tell us what would have helped.