• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: How do I get something like performSelector:(SEL) withObjects:(NSArray *)?
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

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
References: 
 >How do I get something like performSelector:(SEL) withObjects:(NSArray *)? (From: Christoffer Lernö <email@hidden>)
 >Re: How do I get something like performSelector:(SEL) withObjects:(NSArray *)? (From: Daniel Jalkut <email@hidden>)

  • Prev by Date: Trouble with NSManagedObjectContext
  • Next by Date: Re: using zlib on OS X
  • Previous by thread: Re: How do I get something like performSelector:(SEL) withObjects:(NSArray *)?
  • Next by thread: using zlib on OS X
  • Index(es):
    • Date
    • Thread