JavaScriptCore不会将字符串传递为NSObject *

时间:2014-04-15 19:28:54

标签: javascript ios javascriptcore

考虑以下带有NSObject *属性的JSExported objective-c类:

@protocol MyObjectExport <JSExport>
@property (nonatomic, strong) NSObject *myProperty;
@end

@interface MyObject : NSObject <MyObjectExport>
@end

@implementation MyObject
- (NSObject *)myProperty
{
    NSLog(@"in myProperty");
    return nullptr;
}
- (void)setMyProperty:(NSObject *)myProperty
{
    NSLog(@"in setMyProperty");
}
@end

如果我执行此代码:

{
    JSContext *context = [[JSContext alloc] init];
    context[@"myObject"] = [[MyObject alloc] init];
    [context evaluateScript:@"var foo = myObject.myProperty; myObject.myProperty = foo;"];
}

调用myProperty和setMyProperty。

但是如果我执行这段代码:

{
    JSContext *context = [[JSContext alloc] init];
    context[@"myObject"] = [[MyObject alloc] init];
    [context evaluateScript:@"myObject.myProperty = \"foo\";"];
}

未调用setMyProperty,可能是因为“foo”与NSObject *不兼容。

但是,如果我执行此代码:

{
    MyObject *myObject = [[MyObject alloc] init];
    myObject.myProperty = @"foo";
}

调用setMyProperty。

当然,如果我用NSString *替换NSObject *,一切正常。但我需要这个属性才能容纳各种对象类型。

我不控制传递给evaluateScript的内容。但是,有没有一种方法可以编写代码,以便JavaScriptCore在将它传递给objective-c回调之前将普遍转换为“foo”为NSString *?我意识到我可以拦截javascript端的调用并在那里进行必要的调整,但是如果可能的话我想避免这种情况。

1 个答案:

答案 0 :(得分:2)

如果您需要使用多种类型中的一种,则应使用id而不是NSObject *。这将使它成为类似于C中的void *的通用指针。

更好的是,您可以使用JSValue *作为类型,因为-[JSValue is*]消息可以帮助您确定实际传递的类型。不过,这样做的缺点是您的JSValue *属性需要由JSManagedValue * ivars支持,以防止保留周期。有关此内存管理问题的更多信息,请参阅WWDC 2013视频615,大约2/3。