iOS開発-「performSelector may cause a leak because its selector is unknown」警告原因とその解決方法

9395 ワード

問題の説明
文字列作成セレクタを使ってコンパイルしたところ、「performSelector may cause a leak because its selector is unknown」という警告がありました.
検索後、Stocoverflowで満足できる答えを見つけました.お目にかかる http://stackoverflow.com/questions/7017281/performselector-may-cause-a-leak-because-its-selector-is-unknown . 
原因
ARCモードでは、起動時に呼び出した方法の戻り値をどのように処理するかを知る必要があります.この戻り値は任意の値であってもよい.   void ,   int ,   char ,   NSString ,   id など.ARCはヘッダファイルの関数定義によってこれらの情報を得る.ですから、普段使っている静的なセレクタにはこの警告は現れません.これらの情報はコンパイル中に確定されているからです. 
例えば:
...
[someController performSelector:@selector(someMethod)];
...
- (void)someMethod
{
  //bla bla...
}
を使用します   [someController performSelector: NSSelectorFromString(@"someMethod")]; 時ARCはこの方法の戻り値が分かりません.また、どうすればいいですか?無視しますか?それとも   ns_returns_retained まだです  ns_returns_autoreleased ? 
解決策
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.マクロを使って警告を無視する
#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で実行できます.xCode 5は大丈夫ですが、xcode 6の場合はこれは警告を解消できません.