在c函数中使用performSelector来调用委托

时间:2014-08-02 12:18:31

标签: objective-c c exc-bad-access

方案

if (delegate && [delegate respondsToSelector:@selector(aboutTextUpdated:)]) {
    [delegate aboutTextUpdated:aboutText];
}

为了简化我项目中的这种检查,我创建了几个c函数,如下所示。

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
id callSelectorOnDelegateWithObject(SEL selector,NSObject *delegate,id object)
{
    if (delegate != nil && [delegate respondsToSelector:selector] == YES)
    {
        if (object != nil)
        {
            return [delegate performSelector:selector withObject:object];
        }
        else 
        {
            return [delegate performSelector:selector];
        }
    }
    return nil;
}

id callSelectorOnDelegate(SEL selector,NSObject *delegate)
{
    if (delegate != nil && [delegate respondsToSelector:selector] == YES)
    {
        return [delegate performSelector:selector];
    }
    return nil;
}
#pragma clang diagnostic pop

他们被称为如下

callSelectorOnDelegateWithObject(@selector(aboutTextUpdated:), delegate, aboutText);

问题
我有时会出现EXC_BAD_ACCESS错误,但不能以可重现的方式出现。调用c函数但在执行第一个语句之前发生异常。当我用实际的if语句替换函数调用时,错误永远不会发生。为了满足项目的最后期限,我继续进行了这一改变。但是,我无法摆脱这种错误。

导致错误的原因是什么?

更多背景

  • 项目使用ARC,最低目标是iOS 5.0
  • 该项目使用AFNetworking 1. *从服务器获取数据,核心数据保存在应用程序中,NSNotification用于应用程序间通信
  • 执行选择器的方法总是返回void

1 个答案:

答案 0 :(得分:1)

我们需要了解崩溃的详细信息才能了解更多信息。我最好的猜测是偶尔会调用callSelectorOnDelegateWithObject(),其中objectnil,但selector标识的方法实际上确实需要参数。在这种情况下,您只使用-performSelector:,而不是-performSelector:withObject:。因此,该方法接收其参数的垃圾。

如果某些代码调用callSelectorOnDelegateWithObject()而不是callSelectorOnDelegate(),那么您应该无条件地传递object参数。传递nil的呼叫者并不意味着您可以放弃参数。 nil可能(或者至少可能)很重要。

那就是说,这整个方法似乎不是一个好主意。我不会发现这个方案比问题顶部的代码片段更简单。

您可以通过不明确检查delegate是否为非nil来简化该代码段。如果-respondsToSelector:delegate,则nil检查将返回false,因为消息nil始终会导致错误。

最后,您绝不应与YES(或TRUE等)进行比较。您正在使用一个已经是布尔表达式的表达式,然后将其作为复合布尔表达式。让我问你是否会编写如下代码:

if (([delegate respondsToSelector:selector] == YES) == YES)
    ...

如果你不写第二个== YES(以及与YES进行进一步比较的无限序列),那么你应该理解为什么你不应该写第一个。{/ p>

除此之外,任何非零值都是真值。 YES只是一个这样的价值。对于返回布尔值的任何给定方法,您无法确定它返回的真值实际上是YES而不是任何其他真值。