Я пишу класс Button в Objective-C с ARC - Как предотвратить предупреждение утечки памяти Clang на селекторе? - PullRequest
19 голосов
/ 12 августа 2011

Я пишу простой класс кнопок, что-то вроде этого:

@interface MyButton : NSObject {
  id object;
  SEL action;
}
@property(strong) id object;
@property SEL action;
-(void)fire;
@end


@implementation MyButton

@synthesize object, action;

-(void)fire {
  [object performSelector:action];
}

@end

Я получаю следующее предупреждение от Clang о [object performSelector:action]:

PerformSelector may cause a leak because its selector is unknown

После некоторые исследования Я вижу, что селекторы могут принадлежать к семействам, которые имеют разные требования к памяти.Предполагается, что действие вернет void, поэтому оно не должно вызывать каких-либо трудностей ARC и должно соответствовать семейству none.

Похоже, что соответствующий фрагмент кода препроцессора, который я хочу, есть или естьвариант:

__attribute__((objc_method_family(none)))

Но куда мне положить это, чтобы Clang не беспокоиться?

Ответы [ 4 ]

17 голосов
/ 16 августа 2011

Поскольку вы динамически назначаете action, компилятор обнаруживает возможную утечку с ARC.В будущем компилятор LLVM может позволить вам подавить предупреждение.До этого вы можете избежать предупреждения, используя objc_msgSend() среды выполнения вместо -performSelector:.

Сначала импортируйте заголовок сообщения времени выполнения

#import <objc/message.h>
Затем замените performSelector: на objc_msgSend()
    // [object performSelector:action];
    objc_msgSend(object, action);
9 голосов
/ 16 марта 2012

В компиляторе LLVM 3.0 в Xcode 4.2 вы можете подавить предупреждение следующим образом:

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
    [object performSelector:action];
#pragma clang diagnostic pop

Благодаря Скотту Томпсону (об этом похожем вопросе: executeSelector может вызвать утечку, поскольку его селектор неизвестен ) для ответа.

5 голосов
/ 13 августа 2011

Если вы пишете новый код, лучшим способом обработки обратных вызовов является использование блоков;они оба безопаснее и гибче, чем executeSelector.См http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/Blocks/Articles/00_Introduction.html.

1 голос
/ 30 июня 2012

Я использую это:

[object tryToPerform:action with:nil];
...