使用JavascriptCore创建构造函数

时间:2013-11-21 06:14:40

标签: javascript ios objective-c c xcode

使用JavascriptCore API时,我不确定如何通过new语法(ex. var x = new MyAwesomeClass())从Javascript创建Objective-C对象的新实例。看来,在传递符合JSExport-derived protocol的Objective-C类时,在Javascript中创建的构造函数对象应该可以作为构造函数调用,但它们不是。

例如,假设我有一个符合JSExport-derived protocol的类,并将其插入到javascript上下文中:

     @protocol MyAwesomeClassExports <JSExport>
    ...
    @end

    @interface MyAwesomeClass : NSObject <MyAwesomeClassExports>
    ...

    @end



   JSContext *context = ...;
context[@"MyAwesomeClass"] = [MyAwesomeClass class]

然后,如果我尝试通过以下语法在javascript中创建一个新实例:

[object MyAwesomeClassConstructor] is not a constructor

是否可以使用new语法从javascript创建Objective-C对象的新实例?我理想的是将它alloc,然后在Objective-C实例上调用init方法。如果在javascript中传递了任何参数,那么希望通过[JSContext currentArguments]类方法可以在Objective-C init方法中访问这些参数。

6 个答案:

答案 0 :(得分:3)

这就是我一直在使用的。希望这有帮助!

extern void RHJSContextMakeClassAvailable(JSContext *context, Class class){
    NSString *className = NSStringFromClass(class);
    context[[NSString stringWithFormat:@"__%@", className]] = (id) ^(void){ return [[class alloc] init]; };
    [context evaluateScript:[NSString stringWithFormat:@"var %@ = function (){ return __%@();};", className, className]];

    //allow a class to perform other setup upon being loaded into a context.
    SEL selector = NSSelectorFromString(@"classWasMadeAvailableInContext:");
    if ([class respondsToSelector:selector]){
        ((void (*)(id, SEL, JSContext*))[class methodForSelector:selector])(class, selector, context);
    }
}

答案 1 :(得分:3)

一个简单的解决方案是在Obj-C中定义构造函数。

// Inside protocol
+ (MyAwesomeClass *)create;
...

// Inside implementation
+ (MyAwesomeClass *)create
{
  return [[MyAwesomeClass alloc] init];
}

然后在JavaScript中,只需调用此构造函数来创建一个新对象:

obj = MyAwesomeClass.create()

答案 2 :(得分:1)

我知道这很老了,但这对我有用:

context[@"MyClass"] = ^MyClass*{
    return [[MyClass alloc] init];
};

然后来自JavaScript:

var myClass = new MyClass();

答案 3 :(得分:1)

为要从Javascript实例化的类创建协议。它应该扩展JSExport。

@import JavaScriptCore

@protocol EntityExports <JSExport>

@property NSString *somePropertyToExpose
- (instancetype)initWithSomeValue:(NSString *)value;

@end

@interface Enity : NSObject <EntityExports>
@end

并在.m文件中,实现初始化程序并合成属性:

@implementation Entity

@synthesize somePropertyToExpose = _somePropertyToExpose;

- (instancetype)initWithSomeValue:(NSString *)value
{
// implementation goes here
}

@end

然后,在实例化JSContext的代码中:

context[@"Entity"] = [Entity class];

并在Javascript中实例化Entity

var entity = new Entity("hello!");

(请注意,该属性不是构造对象所必需的;它只是为了使示例非平凡)。

答案 4 :(得分:0)

我不确定这个,但我认为你应该首先创建你的Objective-C对象,之后你应该像这样创建JSValue:

MyAwesomeClass *myClass = [[MyAwesomeClass alloc] init];
JSValue *dataValue = [JSValue valueWithObject: myClass inContext:context];

让我知道这是帮助。

答案 5 :(得分:0)

这个问题前几天在Apple开发者论坛中被问到here

据我所知,看起来这是一个已知的缺陷,最近才在WebKit(包括JavaScriptCore)中修复;并且更改不在iOS7中:

https://bugs.webkit.org/show_bug.cgi?id=123380

通过使用JSObjectMake和正确配置的JSClassDefinition,可以在WebKit外部完成此操作吗?我没有时间调查这条路线。