轉(zhuǎn)自:https://blog.csdn.net/majiakun1/article/details/46424925
如何解決使用ARC后出現(xiàn)的PerformSelector may cause a leak because its selector is unknown
問(wèn)題描述
項(xiàng)目中使用到了從字符串創(chuàng)建選擇器,編譯時(shí)發(fā)現(xiàn)警告:"performSelector may cause a leak because its selector is unknown"
(因?yàn)閜erformSelector的選擇器未知可能會(huì)引起泄漏)个从,為什么在ARC模式下會(huì)出現(xiàn)這個(gè)警告痕惋?
經(jīng)過(guò)搜索后碟贾,在Stackoverflow上發(fā)現(xiàn)了一個(gè)令人滿意的答案仇矾。見(jiàn)http://stackoverflow.com/questions/7017281/performselector-may-cause-a-leak-because-its-selector-is-unknown织咧。
原因
在ARC模式下八秃,運(yùn)行時(shí)需要知道如何處理你正在調(diào)用的方法的返回值薛闪。這個(gè)返回值可以是任意值迁霎,如 void,int,char,NSString,id等等冈爹。ARC通過(guò)頭文件的函數(shù)定義來(lái)得到這些信息。所以平時(shí)我們用到的靜態(tài)選擇器就不會(huì)出現(xiàn)這個(gè)警告欧引。因?yàn)樵诰幾g期間频伤,這些信息都已經(jīng)確定。
如:
[someController performSelector:@selector(someMethod)];
- (void)someMethod
{
//bla bla...
}
而使用[someController performSelector: NSSelectorFromString(@"someMethod")];時(shí)ARC并不知道該方法的返回值是什么芝此,以及該如何處理憋肖?該忽略因痛?還是標(biāo)記為ns_returns_retained還是ns_returns_autoreleased?
解決辦法
1.使用函數(shù)指針?lè)绞?/p>
SEL selector = NSSelectorFromString(@"someMethod");
IMP imp = [_controller methodForSelector:selector];
void (*func)(id, SEL) = (void *)imp;
func(_controller, selector);
當(dāng)有額外參數(shù)時(shí),如
SEL selector = NSSelectorFromString(@"processRegion:ofView:");
IMP imp = [_controller methodForSelector:selector];
CGRect (*func)(id, SEL, CGRect, UIView *) = (void *)imp;
CGRect result = func(_controller, selector, someRect, someView);
2.使用宏忽略警告
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[someController performSelector: NSSelectorFromString(@"someMethod")]
#pragma clang diagnostic pop
通過(guò)使用#pragma clang diagnostic push/pop岸更,你可以告訴Clang編譯器僅僅為某一特定部分的代碼來(lái)忽視特定警告鸵膏。
如果需要忽視的警告有多處,可以定義一個(gè)宏
#define SuppressPerformSelectorLeakWarning(Stuff) \
do { \
_Pragma("clang diagnostic push") \
_Pragma("clang diagnostic ignored \"-Warc-performSelector-leaks\"") \
Stuff; \
_Pragma("clang diagnostic pop") \
} while (0)
在產(chǎn)生警告也就是performSelector的地方用使用該宏怎炊,如
SuppressPerformSelectorLeakWarning(
[_target performSelector:_action withObject:self]
);
如果需要performSelector返回值的話谭企,
id result;
SuppressPerformSelectorLeakWarning(
result = [_target performSelector:_action withObject:self]
);
3.使用afterDelay
[self performSelector:aSelector withObject:nil afterDelay:0.0];
如果在接受范圍內(nèi),允許在下一個(gè)runloop執(zhí)行评肆,可以這么做债查。xCode5沒(méi)問(wèn)題,但據(jù)反映瓜挽,xCode6的話這個(gè)不能消除警告盹廷。