performSelector with more than 2 objects
Asked Answered
P

3

17

Is there a way to call [anObject performSelector]; with more than 2 objects? I know you can use an array to pass multiple arguments, but I was wondering if there was a lower level way to call a function I already have defined with more that 2 arguments without using a helper function with an nsarray of arguments.

Phage answered 27/2, 2010 at 8:53 Comment(0)
A
49

Either (1) Use an NSInvocation or (2) directly use objc_msgSend.

objc_msgSend(target, @selector(action:::), arg1, arg2, arg3);

(Note: make sure all arguments are id's, otherwise the arguments might not be sent correctly.)

Asthenic answered 27/2, 2010 at 9:2 Comment(2)
When using objc_msgSend, you'll need to #import <objc/message.h> as per: #4897010Ostraw
that last note you made about making sure all args are of type id's.. can you explain further? or provide some resource please? i cant find any.Equites
D
14

You can extend the NSObject class like this:

- (id) performSelector: (SEL) selector withObject: (id) p1
       withObject: (id) p2 withObject: (id) p3
{
    NSMethodSignature *sig = [self methodSignatureForSelector:selector];
    if (!sig)
        return nil;

    NSInvocation* invo = [NSInvocation invocationWithMethodSignature:sig];
    [invo setTarget:self];
    [invo setSelector:selector];
    [invo setArgument:&p1 atIndex:2];
    [invo setArgument:&p2 atIndex:3];
    [invo setArgument:&p3 atIndex:4];
    [invo invoke];
    if (sig.methodReturnLength) {
        id anObject;
        [invo getReturnValue:&anObject];
        return anObject;
    }
    return nil;
}

(See NSObjectAdditions from the Three20 project.) Then you could even extend the above method to use varargs and nil-terminated array of arguments, but that’s overkill.

Dark answered 27/2, 2010 at 9:46 Comment(0)
A
0

An additional option, when you require to send multiple objects with performSelector is (if it's easy enough to do) to amend the method you wish to call to take an NSDictionary object instead of multiple parameters, as you'll be able to send as many as you like within the dictionary.

For example

I had a method similar to this which had 3 arguments and I needed to call it from performSelector -

-(void)getAllDetailsForObjectId:(NSString*)objId segment:(Segment*)segment inContext:(NSManagedObjectContext*)context{

I changed this method to make use of a dictionary to store the arguments

-(void)getAllDetailsForObject:(NSDictionary*)details{

therefore I was able to call the method easily

[self performSelector:@selector(getAllDetailsForObject:) withObject:@{Your info stored within a dictionary}];

Thought I'd be as well sharing this as an alternative option as it works for me.

Cheers

Ancestry answered 10/2, 2015 at 11:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.