The protocol you implement to export Objective-C classes and their instance methods, class methods, and properties to JavaScript code.
SDKs
- iOS 7.0+
- macOS 10.9+
- Mac Catalyst 13.0+
- tvOS 9.0+
Framework
- Java
Script Core
Declaration
protocol JSExport
Overview
Exporting Objective-C Objects to JavaScript
When you create a JavaScript value from an instance of an Objective-C class, and the JSValue
class does not specify a copying convention, JavaScriptCore creates a JavaScript wrapper object. (For certain classes, JavaScriptCore automatically copies values to the appropriate JavaScript type; for example, NSString
instances become JavaScript strings.)
In JavaScript, inheritance is supported via a chain of prototype objects. For each Objective-C class you export, JavaScriptCore creates a prototype within the enclosing JavaScript context (a JSContext
object). For the NSObject
class, the prototype object is the JavaScript context's Object
prototype. For all other Objective-C classes, JavaScriptCore creates a prototype object whose internal [Prototype]
property points to the prototype property created for the Objective-C class's superclass. As such, the prototype chain for a JavaScript wrapper object reflects the wrapped Objective-C type's inheritance hierarchy.
In addition to the prototype object, JavaScriptCore produces a JavaScript constructor object for each Objective-C class.
Exposing Objective-C Methods and Properties to JavaScript
By default, no methods or properties of the Objective-C class are exposed to JavaScript; instead, you must choose methods and properties to export. For each protocol that a class conforms to, if the protocol incorporates the JSExport
protocol, then JavaScriptCore interprets that protocol as a list of methods and properties to be exported to JavaScript.
For each instance method exported, JavaScriptCore creates a corresponding JavaScript function as a property of the prototype object. For each Objective-C property exported, JavaScriptCore creates a JavaScript accessor property on the prototype. For each class method exported, JavaScriptCore creates a JavaScript function on the constructor object. For example, Listing 1 and Listing 2 illustrate adoption of the JSExport
protocol and the API presented by an exported class in JavaScript.
Exporting an Objective-C Class to JavaScript
@protocol MyPointExports <JSExport>
@property double x;
@property double y;
- (NSString *)description;
- (instancetype)initWithX:(double)x y:(double)y;
+ (MyPoint *)makePointWithX:(double)x y:(double)y;
@end
@interface MyPoint : NSObject <MyPointExports>
- (void)myPrivateMethod; // Not in the MyPointExports protocol, so not visible to JavaScript code.
@end
@implementation MyPoint
// ...
@end
Using an Exported Objective-C Class from JavaScript
// Objective-C properties become fields.
point.x;
point.x = 10;
// Objective-C instance methods become functions.
point.description();
// Objective-C initializers can be called with constructor syntax.
var p = MyPoint(1, 2);
// Objective-C class methods become functions on the constructor object.
var q = MyPoint.makePointWithXY(0, 0);
The attributes of an Objective-C @property
declaration determine the attributes of the corresponding JavaScript property:
If the Objective-C property is declared
readonly
, the JavaScript property has the attributeswritable: false
,enumerable: false
,configurable: true
.If the Objective-C property is declared
readwrite
, the JavaScript property has the attributeswritable: true
,enumerable: true
,configurable: true
.
Wrapped Objective-C properties, parameters, and return values convert according to the copying convention specified by the JSValue
class for their types. . See JSValue
for the complete list of copying conventions.
Note
If a class declares conformance to the JSExport
protocol, JavaScriptCore ignores its normal copying conventions for built-in types. For example, if you define a custom NSString
subclass that conforms to the JSExport
protocol and pass an instance of that class to the valueWithObject: method, the result is a JavaScript wrapper object for the custom class, not a JavaScript string primitive.
Customizing Export of Objective-C Selectors
When exporting a selector that takes one or more arguments, JavaScriptCore generates a corresponding function name using the following conversion:
All colons are removed from the selector.
Any lowercase letter that had followed a colon is capitalized.
For example, under the default conversion the Objective-C selector do
is exported as the JavaScript function do
.
To rename a selector exported to JavaScript, use the JSExport
macro. For example, to instead export the Objective-C selector do
as the JavaScript function do
, use the following declaration:
@protocol MyClassJavaScriptMethods <JSExport>
JSExportAs(doFoo,
- (void)doFoo:(id)foo withBar:(id)bar
);
@end
Note
The JSExport
macro may only be applied to a selector that takes one or more arguments.