Is JavaScript applicable as a method in objective-c?

So basically I am implementing a typical way to handle JavaScript calls in objc using window.location = "myobj: mymethod: myarg: myotherarg", however I am wondering if there is a way to apply an array of arguments to a method similar to how you can in JavaScript .

I usually did

-(void) mymethod:(NSArray*) arr{
    //method knows how many arguments it takes and what they mean at each index
}

I would prefer:

-(void) mymethod:(NSString*) myarg myOtherArg: (NSString*) myotherarg{
    //do stuff
}

and have a method like this:

+(void) callMethod:(NSString*)selectorName withArgs: (NSArray*)args onObject:(id) obj{
    //implementation
}
[JEHelpers callMethod:selector withArgs:someArrayOfArgs onObject:myapp]

Is it possible?

+5
source share
4 answers

If you know that no method will take more than two arguments, you can use performSelector:withObject:withObject:to make these calls. If the method takes less than two arguments, unused fields withObject:will be ignored.

+ (id)callMethod:(NSString *)selectorName withArgs:(NSArray *)args onObject:(id)obj {
    id arg1 = nil, arg2 = nil;
    if([args count]) {
        arg1 = [args objectAtIndex:0];
        if([args count] > 1])
           arg2 = [args objectAtIndex:1];
    }
    return [obj performSelector:NSSelectorFromString(selectorName)
                     withObject:arg1 withObject:arg2];
}

, NSInvocation. , , .

+ (id)callMethod:(NSString *)selectorName withArgs:(NSArray *)args onObject:(id)obj {
    SEL sel = NSSelectorFromString(selectorName);
    NSMethodSignature *signature = [obj methodSignatureForSelector:sel];
    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
    [invocation setSelector:sel];
    [invocation setTarget:obj];
    NSUInteger index = 2;
    for(id arg in args) {
        [invocation setArgument:&arg atIndex:index];
        ++index;
    }
    id result;
    [invocation setReturnValue:&result];
    [invocation invoke];
    return result;
}
+2

, ( JavaScript). NSInvocation . - :

+(void) callMethod:(NSString*)selectorName withArgs: (NSArray*)args onObject:(id) obj
{
    SEL selector = NSSelectorFromString(selectorName);
    if (![obj respondsToSelector:selector]) {
        // Object doesn't respond to selector, so do something else/handle the error
    }
    NSMethodSignature *methodSignature = [obj methodSignatureForSelector:selector];
    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature];
    [invocation setTarget:obj];
    [invocation setSelector:selector];
    for (NSUInteger i=0; i<[args count]; i++) {
        id argument = [args objectAtIndex:i];
        [invocation setArgument:&argument atIndex:i+2]; // Arg 0 is self, arg 1 is _cmd
    }
    id result;
    [invocation setReturnValue:&result];
    [invocation invoke];
}
+2

, NSInvocation. , NSInvocation selectorName (NSObject -methodSignatureForSelector:), , . : (NSMethodSignature -getArgumentTypeAtIndex:, "@" ), , , 2 ( 0 1 - self ).

I am not saying that this is a good idea, by the way; there are very few cases where this approach is justified.

+1
source

This is a bit awkward, but possible:

- (id)method:(NSString *)arg1, ... {
  va_list args;
  va_start(args, arg1);
  for (NSString *a = arg1; a!= nil; a= va_arg(args, NSString*)) {
    // do stuff
  }
}

It arg1will usually be a string that defines the data types and the number of additional parameters.

You would call it this way:

[self method:@"5", @"4", @"3", @"2", @"1"];

Your array method is probably more clear for most purposes.

0
source

All Articles