views:

32

answers:

3

Hi, there! I have defined a protocol like this:

@protocol RSSItemParserDelegate <NSObject>
- (void)RSSItemParser:(RSSItemParser *)parser
didEndParsingSuccesfully:(BOOL)success;
@end

And I am calling this method when some parsing is finished, on success YES and on failure NO, like this:

[delegate RSSItemParser:self didEndProcessSuccesfully:NO];

But I would like it to run in the main thread asynchronously. How can I do this?

I think performSelectorOnMainThread:withObject:waitUntilDone: would work with a solely argument method, but how about methods with two arguments like mines? specially when working with AVFoundation and CoreVideo there are a lot of delegates methods that have more than 2 arguments, I wonder how are they called.

Thanks

Ignacio

+1  A: 

There are plenty of ways to do this. You could use the NSInvocation API to create an invocation object that you then use one of the performSelector... methods on (because invoke and its kin take 0 or 1 parameters). Or, you could create an internal wrapper method that takes a single "context" object (a struct or dictionary) that wraps up all the values you need to pass to your delegate. Then, perform that method on the main thread and unpack the context values to pass them to your actual delegate method. Or, you can just pass the context object to your delegate directly and let it do the unpacking.

warrenm
Thanks, Could you show an example? I may be misunderstanding this, but I think it resembles drawnonward's answer, only it uses NSInvocation.
nacho4d
A: 

The easy way is to make a method that only needs one argument. In you case, make a delegate call method:

-(void) invokeDelegateWithDidEndProcessSuccesfully:(NSNumber)success {
  [delegate RSSItemParser:self didEndProcessSuccesfully:[success boolValue]];
}

Then use it:

-(void) didEndParsingSuccesfully:(BOOL)success {
  [self performSelectorOnMainThread:@selector(invokeDelegateWithDidEndProcessSuccesfully) withObject:[NSNumber numberWithBool:success] waitUntilDone:NO];
}

The hard way is to use an NSInvocation to handle an arbitrary number of arguments. None of the arguments are implicitly retained.

drawnonward
Thanks for you answer, this is actually what I am doing right now. But I thought there should be a more "elegant" or "correct" way of doing this.
nacho4d
+1  A: 
SEL action = @selector(actionWithFoo:bar:baz:);
NSInvocation * i = [NSInvocation invocationWithMethodSignature:[target methodSignatureForSelector:action]];
[i retainArguments];
[i setTarget:target];
[i setAction:action];
[i setArgument:&foo atIndex:2];
[i setArgument:&bar atIndex:3];
[i setArgument:&baz atIndex:4];
[i performSelectorOnMainThread:@selector(invoke) withObject:nil waitUntilDone:NO];

Much easier and more extensible to just use a dictionary.

tc.
This is an excellent example of using NSInvocation and is perfect for my needs. Thanks;)
nacho4d