iOS實現調用動態方法名有返回值的方法

需求:html

有10個類, 每一個類裏頭都有n個方法(前提是方法名有規律可循,好比 setA0,setA1…)  若是挨個去init類, 而後挨個調用方法,這樣你一天就不用幹別的了ios

簡單的解決方法能夠參考這個: iPhone開發中,動態調用類和方法git

雖說performSelector有返回值,可是在ARC下會有警告,由於方法名是動態的,系統並不知道返回值是什麼樣的類型。解決方法能夠見這篇文章: "performSelector may cause a leak because its selector is unknown"警告緣由及其解決辦法github

全文轉載過來:函數

問題描述

項目中使用到了從字符串建立選擇器,編譯時發現警告:"performSelector may cause a leak because its selector is unknown"(由於performSelector的選擇器未知可能會引發泄漏),爲何在ARC模式下會出現這個警告?oop

通過搜索後,在Stackoverflow上發現了一個使人滿意的答案。見http://stackoverflow.com/questions/7017281/performselector-may-cause-a-leak-because-its-selector-is-unknownspa

緣由

在ARC模式下,運行時須要知道如何處理你正在調用的方法的返回值。這個返回值能夠是任意值,如void,int,char,NSString,id等等。ARC經過頭文件的函數定義來獲得這些信息。因此平時咱們用到的靜態選擇器就不會出現這個警告。由於在編譯期間,這些信息都已經肯定。指針

如:code

...
[someController performSelector:@selector(someMethod)];
...
- (void)someMethod
{  //bla bla...}

而使用[someController performSelector: NSSelectorFromString(@"someMethod")];時ARC並不知道該方法的返回值是什麼,以及該如何處理?該忽略?仍是標記爲ns_returns_retained仍是ns_returns_autoreleased?orm

解決辦法

1.使用函數指針方式

SEL selector = NSSelectorFromString(@"someMethod");IMP imp = [_controller methodForSelector:selector];void (*func)(id, SEL) = (void *)imp;func(_controller, selector);

當有額外參數時,如

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

經過使用#pragma clang diagnostic push/pop,你能夠告訴Clang編譯器僅僅爲某一特定部分的代碼來忽視特定警告。

若是須要忽視的警告有多處,能夠定義一個宏

#define SuppressPerformSelectorLeakWarning(Stuff) \    do { \        _Pragma("clang diagnostic push") \        _Pragma("clang diagnostic ignored \"-Warc-performSelector-leaks\"") \
        Stuff; \        _Pragma("clang diagnostic pop") \
    } while (0)

在產生警告也就是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];

若是在接受範圍內,容許在下一個runloop執行,能夠這麼作。xCode5沒問題,但據反映,xCode6的話這個不能消除警告。

相關文章
相關標籤/搜索