1

[不重复:仔细阅读问题和已经给出的答案,我已经阅读过]

我正面临这个问题,我需要替换-performSelector方法,因为它会在带有 ARC 的编译器中引起该警告

performSelector 可能会导致泄漏,因为它的选择器是未知的

我知道关于该主题有不同的问题:

而且我也知道避免该警告的技术。
有时作为一种解决方案,我发现最建议的建议是使用dispatch_async(dispatch_get_main_queue(),^(void) { WHATEVER }); ,但据我所知,调度需要在下一个运行循环中执行块,-performSelector(没有延迟)立即执行。
为什么要进行这种精神自慰?想象一下,您正在使用新的 Gamekit 方法进行身份验证,game kit 可以在 auth 块内部向您发送一个视图控制器,以使用户进行一些操作(例如创建 id、登录等)。如果他/她想要查看该视图控制器,警告用户可能很有用。为此,我正在编写一个协议。特别是该方法应该返回一个 BOOL - (BOOL)shouldLoadGameKitViewController: (UIViewController*) viewController;,我想使用它来调用它-performSelector. 重点是,如果方法没有立即返回,我就无法从代表那里得到答案。
我正在使用 NSInvocation 来实现这一点,但是很冗长,是否存在其他方式?

[使用代码更新]
请注意,现在我正在使用调用,线程检查部分仍未实现。评论有给出警告的部分

- (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");
}

[某种解决方案仍未测试]

- (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;
}

使用 NSMethodSignature 方法,可以加速,并要求返回类型。我仍然没有测试,但它应该成功了。

4

2 回答 2

-1

您可以使用dispatch_sync而不是dispatch_async立即执行块(您的代码将被阻止,直到块返回)。

另一种选择是暂时抑制警告,如this answer中所述。

于 2013-06-03T14:45:53.320 回答
-1

尝试这样做以避免泄漏或“未知选择器发送到实例”问题:

SEL selector = NSSelectorFromString(@"methodName::");
if ([obj respondsToSelector:selector])
    [obj performSelector:selector withObject@[args,array]];
于 2013-06-03T14:33:03.613 回答