Переменный список аргументов для блока JavascriptCore

Я хотел бы определить функцию в контексте JavascriptCore, которая принимает переменное количество аргументов.

Что-то вроде этого:

JSVirtualMachine* virtualMachine = [[JSVirtualMachine alloc] init];
JSContext* ctx = [[JSContext alloc] initWithVirtualMachine:virtualMachine];

ctx[@"func"] = ^(JSValue* value, ...){
    va_list args;
    va_start(args, value);
    for (JSValue *arg = value; arg != nil; arg = va_arg(args, JSValue*)) {
        NSLog( @"%@", arg);
    }
    va_end(args);
};

[ctx evaluateScript:@"func('arg1', 'arg2');"];

Я считаю, что оболочка JSC не передает второй аргумент в блок, потому что итерация по va_list завершается сбоем после регистрации первого аргумента.

Я также пробовал с соглашением NSArray*, оно не работает.

Возможно ли это каким-либо образом?


person ldiqual    schedule 11.02.2014    source источник
comment
Я также пытался сделать это при определении обработчика журнала консоли Objective-C, который принимал несколько аргументов, но не смог заставить его работать даже с помощью NSLogv. Беспорядочный подход - вы можете попробовать сериализовать аргументы в один аргумент через JSON, а затем распаковать его в обработчике Objective-C.   -  person Mike    schedule 11.02.2014
comment
Да, это был бы крайний вариант. На самом деле есть способ сделать это с помощью обычного C API с JSObjectMakeFunctionWithCallback, но я хотел бы отказаться от этого интерфейса C, чтобы ARC мог обрабатывать память JS Value.   -  person ldiqual    schedule 11.02.2014


Ответы (2)


Из AOContext.h:

// This method may be called from within an Objective-C block or method invoked
// as a callback from JavaScript to retrieve the callback's arguments, objects
// in the returned array are instances of JSValue. Outside of a callback from
// JavaScript this method will return nil.
+ (NSArray *)currentArguments;

Приводя к следующему:

ctx[@"func"] = ^{
    NSArray *args = [JSContext currentArguments];
    for (JSValue *arg in args) {
        NSLog( @"%@", arg);
    }
};

[ctx evaluateScript:@"func('arg1', 'arg2');"];
person erm410    schedule 13.04.2014
comment
Это также отличный способ получить объекты JSValue из аргументов. Только что понял, что получение JSValues ​​в качестве аргументов блока (например, ctx[@"func"] = ^(JSValue* value){...}) приводит к утечке переданных значений. Похоже, что блок сохраняет значение, поэтому контекст сохраняет блок, блок сохраняет значение, а значение сохраняет контекст. - person Micha Mazaheri; 22.09.2014

Мне нравится ответ @ erm410, я не видел документацию по currentArguments.

Другой подход, который я использовал, заключается в передаче объекта JSON в NSDictonary цели-C. Одним из преимуществ этого подхода является то, что у вас есть именованные аргументы, хотя вы имеете дело со строковыми литералами, которые должны быть правильно введены между вызовом и обработчиком.

ctx[@"func"] = ^(NSDictionary *args) {
    NSLog(@"%@", args[@"arg1"];
};

[ctx evaluateScript:@"func({'arg1':'first','arg2':'second'})"];
person Jeff Hopper    schedule 06.05.2014