Skip to content

Instantly share code, notes, and snippets.

@zgramana
Created October 29, 2011 00:25
Show Gist options
  • Save zgramana/1323909 to your computer and use it in GitHub Desktop.
Save zgramana/1323909 to your computer and use it in GitHub Desktop.
Code snippet for Spawning Threads Using Selectors With Multiple Parameters
/* Copyright (c) 2011 Zachary J. Gramana
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
- (void)performSelector:(SEL)aSelector
withValues:(void *)context, ...
{ // See if we were even passed any context.
if (context)
{
// We'll need an NSInvocation, since it lets us define arguments
// for multiple parameters.
NSMethodSignature *theSignature = [self methodSignatureForSelector:aSelector];
NSInvocation *theInvocation = [NSInvocation invocationWithMethodSignature:theSignature];
[theInvocation retainArguments];
// Now for the real automagic fun! We will loop through our arugment list,
// and match up each parameter with the corresponding index value.
// Since Objective-C actually converts messages into C methods:
NSUInteger argumentCount = [theSignature numberOfArguments] - 2;
[theInvocation setTarget:self]; // There's our index 0.
[theInvocation setSelector:aSelector]; // There's our index 1.
// Use the va_* macros to retrieve the arguments.
va_list arguments;
// Tell it where the optional args start.
// Since the first parameter, the selector
// Isn't optional, tell it to start with 'context'.
va_start (arguments, context);
// Now for arguments 2+
NSUInteger i, count = argumentCount;
void* currentValue = context;
for (i = 0; i < count; i++)
{
// If we run out of arguments, then we pass nil
// to the remaining parameters.
[theInvocation setArgument:&currentValue atIndex:(i + 2)]; // The +2 represents self and cmd offsets
currentValue = va_arg(arguments, void*); // Read the next argument in the list.
// We should also handle the case where we have
// *more* arguments than parameters. This will
// let us cover cases where we are invoking
// other variadic methods (like arrayWithObjects:).
}
// Dispose of our C byte-array.
va_end (arguments);
// That's it! (For configuring our NSInvocation).
// In this example, we are going to invoke all
// methods on a custom worker thread.
NSThread *customWorkerThread = [EBCustomThread sharedCustomThread];
// Invoke on our custom worker thread.
[theInvocation performSelector:@selector(invoke) onThread:customWorkerThread withObject:nil waitUntilDone:NO];
// Our NSInvocation is already autoreleased, so we're done.
} else {
// Since we were not given any context arguments,
// just do a non-blocking invocation on a background thread.
// We really would want to check to see that the selector
// is valid, takes no arguments, etc., but that is left
// as an exercise for the reader.
[self performSelectorInBackground:aSelector withObject:nil];
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment