Re: How do I get something like performSelector:(SEL) withObjects:(NSArray *)?
Re: How do I get something like performSelector:(SEL) withObjects:(NSArray *)?
- Subject: Re: How do I get something like performSelector:(SEL) withObjects:(NSArray *)?
- From: Christoffer Lernö <email@hidden>
- Date: Sun, 25 Sep 2005 09:25:51 +0200
On Sep 25, 2005, at 01:50 , Daniel Jalkut wrote:
On Sep 24, 2005, at 7:10 PM, Christoffer Lernö wrote:
I was thinking it should look something along the lines of:
-(void)performSelector:(SEL)aSelector withObjects:(NSArray *)anArray
Can you explain more specifically what the requirements are? I
assume you don't want to simply have each of the delegate's
callbacks parse the contents of the objects array itself?
Basically what happens is that I have parsed a string, separating out
the arguments into a NSArray. Together with these arguments I have a
dictionary mapping which matches those arguments to a multi-parameter
function so that given a string like
"areYou hungry today kid?"
and a mapping looking like
{ areYou = ( areYou, time, who ) }
I am generating a call to looking like:
[someObject areYou:@"hungry" time:@"today" who:@"kid"]
Well the actual code is a bit more flexible, but this is the geist of
it.
What I want to do is to map a string to a normal-looking method,
making the call from the script/string look exactly like a call from
any other method.
The initial method was having something like [someObject areYou:
(NSDictionary *)allArguments], and then each method had to extract
things by hand.
The underlying C function, objc_msgSend, is a varargs function, so
you can (as far as I know) pass it as many arguments as you want. I
assume it was just a case of "we have to stop somewhere" that the
standard NSObject only exposes methods for 1 and 2 arguments.
There is the objc_msgSendv that might do what I want, but I can't
seem to figure out how to populate it's margs properly.
The problem is figuring out how to parse the array and suitably map
the contents of the array to a compilable, linkable, objc_msgSend
call. You might be able to use some assembly glue to set it up for
"any number of arguments," but you would probably get just as much
utility (and more portability) out of writing something gnarly that
can handle "up to as many arguments as I'm likely to use." This
might work (typed into Mail):
-(id) performSelector:(SEL)theSelector withOrderedArguments:
(NSArray*)myArgs
{
switch([myArgs count])
{
case 0: return [self performSelector:theSelector];
case 1: return [self performSelector:theSelector withObject:
[myArgs objectAtIndex:0]];
case 2: return [self performSelector:theSelector withObject:
[myArgs objectAtIndex:0] withObject:[myArgs objectAtIndex:1]];
case 3: return objc_msgSend(self, theSelector, [myArgs
objectAtIndex:0], [myArgs objectAtIndex:1], [myArgs objectAtIndex:2]);
case 4: return objc_msgSend(self, theSelector, [myArgs
objectAtIndex:0], [myArgs objectAtIndex:1], [myArgs objectAtIndex:
2], [myArgs objectAtIndex:3]);
case 5: return objc_msgSend(self, theSelector, [myArgs
objectAtIndex:0], [myArgs objectAtIndex:1], [myArgs objectAtIndex:
2], [myArgs objectAtIndex:3], [myArgs objectAtIndex:4]);
case 6: return objc_msgSend(self, theSelector, [myArgs
objectAtIndex:0], [myArgs objectAtIndex:1], [myArgs objectAtIndex:
2], [myArgs objectAtIndex:3], [myArgs objectAtIndex:4], [myArgs
objectAtIndex:5]);
default: [NSException raise:@"BooHooHoo"
format:@"performSelector:withOrderedArguments: called with too many
arguments. Add more case statements."]; break;
}
return nil;
}
Am I on the right track?
The above gives the result I want, as does wrapping the call in an
NSInvocation, but it seems rather messy for something that should be
rather simple?
This is the best I can do, but why do I have to pass things by
reference in this roundabout manner? I suspect I am doing something
wrong...
SEL aSelector = NSSelectorFromString(selectorString);
if (aSelector && [target respondsToSelector:aSelector])
{
NSInvocation* invocation = [NSInvocation
invocationWithMethodSignature:[target
methodSignatureForSelector:aSelector]];
id arguments[[values count]];
for (int i = 0; i < [values count]; i++)
{
arguments[i] = [values objectAtIndex:i];
[invocation setArgument:&arguments[i] atIndex:i + 2];
}
[invocation setSelector:aSelector];
[invocation invokeWithTarget:target];
}
/Christoffer
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden