考虑以下带有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端的调用并在那里进行必要的调整,但是如果可能的话我想避免这种情况。
答案 0 :(得分:2)
如果您需要使用多种类型中的一种,则应使用id
而不是NSObject *
。这将使它成为类似于C中的void *
的通用指针。
更好的是,您可以使用JSValue *
作为类型,因为-[JSValue is*]
消息可以帮助您确定实际传递的类型。不过,这样做的缺点是您的JSValue *
属性需要由JSManagedValue *
ivars支持,以防止保留周期。有关此内存管理问题的更多信息,请参阅WWDC 2013视频615,大约2/3。