[NOT DUPLICATE: read well the question and the already given answers, I've already read them]
I'm facing that problem, I need to substitute -performSelector
method since it causes that warning in the compiler with ARC
performSelector may cause a leak because its selector is unknown
I'm aware that there different questions about that topic:
and I'm also aware about the techniques to avoid that warning.
Sometimes as a solution I found that the most suggested advice is to use dispatch_async(dispatch_get_main_queue(),^(void) { WHATEVER });
but as far as I know dispatching would require the execution of the block in the next run loop, -performSelector
(without delay) is executed immediately.
Why this mental masturbation? Imagine that you are using the new Gamekit method for authentication, game kit could send you inside the auth block a view controller to make the user do some operation (such as creating the id, log in, etc). It could be useful to warn the user if he/She wants to see that view controller. To do that and other stuffs I'm writing a protocol. In particular that method should return a BOOL - (BOOL)shouldLoadGameKitViewController: (UIViewController*) viewController;
, I'd like to call it using -performSelector
. Here is the point, if the method dosen't return immediately I can't get the answer from the delegate.
I'm using NSInvocation to make that happen but is verbose, does exist some other way?
[UPDATE WITH CODE]
Pay attention that now I'm using invocation, the thread-check part is not still implemented. Commented there is the part that gave the warning
- (void) dispatchToDelegate: (SEL) selector withArg: (id) arg error: (NSError*) err
{
NSMethodSignature *methodSig = [[self class] instanceMethodSignatureForSelector:selector];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSig];
[invocation setTarget:self.delegate];
if([self.delegate respondsToSelector: selector])
{
if(arg != NULL) {
[invocation setArgument:&arg atIndex:2];
[invocation setArgument:&err atIndex:3];
// [_delegate performSelector: selector withObject: arg withObject: err];
}else {
[invocation setArgument:&err atIndex:2];
// [_delegate performSelector: selector withObject: err];
}
[invocation invoke];
}
else
DLog(@"Method not implemented in the delegate");
}
[SORT OF SOLUTION STILL UNTESTED]
- (BOOL) dispatchToDelegate: (SEL) selector withArg: (id) arg error: (NSError*) err
{
NSMethodSignature *methodSig = [[self class] instanceMethodSignatureForSelector:selector];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSig];
[invocation setTarget:self.delegate];
BOOL result = NO;
if([self.delegate respondsToSelector: selector])
{
if(arg != NULL) {
[invocation setArgument:&arg atIndex:2];
[invocation setArgument:&err atIndex:3];
// [_delegate performSelector: selector withObject: arg withObject: err];
}else {
[invocation setArgument:&err atIndex:2];
// [_delegate performSelector: selector withObject: err];
}
if ([NSThread isMainThread]) {
[invocation invoke];
}
else{
[invocation performSelectorOnMainThread:@selector(invoke) withObject:nil waitUntilDone:YES];
}
[invocation getReturnValue:&result];
}
else
NSLog(@"Missed Method");
return result;
}
Using the NSMethodSignature method, is possible to gear up, and ask for the return type. I still didn't test but it should made the trick.