简体   繁体   中英

JavaScriptCore Won't Pass string as NSObject *

Consider the following JSExported objective-c class with an NSObject * property:

@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

If I execute this code:

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

Both myProperty and setMyProperty are called.

But if I execute this code:

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

setMyProperty is not called, presumably because "foo" is not compatible with NSObject *.

However, if I execute this code:

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

setMyProperty is called.

Of course, if I replace NSObject * with NSString *, everything works fine. But I need this property to be able to hold a variety of object types.

I don't control what is passed to evaluateScript. However, is there a way that I can code things so that JavaScriptCore will universally convert "foo" to an NSString * prior to passing it to the objective-c callback? I realize I can intercept the call on the javascript side and do the necessary fiddling there, but I'd like to avoid that if possible.

If you need to hold one of many types you should use id rather than NSObject * . This will make it a generic pointer kind of like a void * in C.

Even better you could use a JSValue * as the type since the -[JSValue is*] messages can help you figure out what type was actually passed. The downside of this though is that your JSValue * properties need to be backed by JSManagedValue * ivars to prevent retain cycles. See WWDC 2013 video 615, about 2/3 of the way through for more on this memory management issue.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM