接收器类型不好' SEL'

时间:2014-03-30 18:42:09

标签: ios objective-c

我是Objective-C和iOS(3天前)的新手。 我正在尝试解决警告'PerformSelector可能导致泄漏,因为它的选择器未知'

SEL _mySelector;
id _myTarget;
NSMutableData * _myJsonData ;
[_responseTarget performSelector:_responseSelector withObject:_myJsonData]; // Warning here

我已将其更改为此

    IMP imp = [_responseTarget methodForSelector:[_responseSelector withObject:_myJsonData]]; //Errors!
    void (*func)(id, SEL) = (void *)imp;
    func(_myTarget, _mySelector);

错误的“接收器类型不好'SEL'”

感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

首先发出警告,因为自动内存管理(ARC)需要知道方法调用结果的类型和所有权,以确定如何管理任何返回的对象引用。

performSelector与变量选择器值一起使用不提供此信息 - 目标C中的选择器值(类型SEL)不携带类型信息。没有类型信息,安全的假设是不进行内存管理,但这可能会导致泄漏,因此警告。

在你的情况下,你似乎期待一个返回类型为void的选择器,如果没有返回任何内容,则不会泄露任何内容。

您试图通过获取方法的类型函数指针并调用它来避免这种情况,除非您犯了错误。错误“错误接收器类型'SEL'”指的是方法调用[_responseSelector withObject:_myJsonData] - 选择器不是对象,您不能发送消息!您似乎要做的是为预先绑定到函数指针的方法提供一个参数(_myJsonData),并在其中提供另外两个参数(_myTarget_mySelector)电话。你为什么要这样做还不清楚(也许你是一个Haskell用户?)。

解决方案很简单,不要尝试预先绑定参数:

IMP imp = [_myTarget methodForSelector:_mySelector];
void (*func)(id, SEL, NSMutableData *) = (void *)imp;
func(_myTarget, _mySelector, _myJsonData);

但是有一种不同的方法可能:你知道你什么都没有返回(void)你可以指示编译器只是关闭performSelector调用的警告:

    // avoid warning on performSelector - return is void so leak not possible
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
    (void)[_myTarget performSelector:_mySelector withObject:_myJsonData];
#pragma clang diagnostic pop

HTH