我是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'”
感谢您的帮助。
答案 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