@interface NSObject (UICaboodle) - (id) yieldToSelector:(SEL)selector withObject:(id)object; - (id) yieldToSelector:(SEL)selector; @end @implementation NSObject (UICaboodle) - (void) doNothing { } - (void) _yieldToContext:(NSMutableArray *)context { _pooled SEL selector(reinterpret_cast([[context objectAtIndex:0] pointerValue])); id object([[context objectAtIndex:1] nonretainedObjectValue]); volatile bool &stopped(*reinterpret_cast([[context objectAtIndex:2] pointerValue])); /* XXX: deal with exceptions */ id value([self performSelector:selector withObject:object]); NSMethodSignature *signature([self methodSignatureForSelector:selector]); [context removeAllObjects]; if ([signature methodReturnLength] != 0 && value != nil) [context addObject:value]; stopped = true; [self performSelectorOnMainThread:@selector(doNothing) withObject:nil waitUntilDone:NO ]; } - (id) yieldToSelector:(SEL)selector withObject:(id)object { /*return [self performSelector:selector withObject:object];*/ volatile bool stopped(false); NSMutableArray *context([NSMutableArray arrayWithObjects: [NSValue valueWithPointer:selector], [NSValue valueWithNonretainedObject:object], [NSValue valueWithPointer:const_cast(&stopped)], nil]); NSThread *thread([[[NSThread alloc] initWithTarget:self selector:@selector(_yieldToContext:) object:context ] autorelease]); [thread start]; NSRunLoop *loop([NSRunLoop currentRunLoop]); NSDate *future([NSDate distantFuture]); while (!stopped && [loop runMode:NSDefaultRunLoopMode beforeDate:future]); return [context count] == 0 ? nil : [context objectAtIndex:0]; } - (id) yieldToSelector:(SEL)selector { return [self yieldToSelector:selector withObject:nil]; } @end