Я пишу класс Button в Objective-C с ARC - Как предотвратить предупреждение утечки памяти Clang на селекторе?
Я пишу простой кнопочный класс, что-то вроде этого:
@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
После некоторые исследования Я вижу, что селекторы могут принадлежать семьям, которые имеют разные требования к памяти. Цель состоит в том, чтобы действие вернуло пустоту, поэтому оно не должно вызывать никаких проблем с ARC и должно вписываться в семейство none
.
Похоже, что соответствующий фрагмент кода препроцессора, который я хочу, является или представляет собой вариант:
__attribute__((objc_method_family(none)))
Но где я могу сказать, что Клану нечего беспокоиться?
Ответы
Ответ 1
В компиляторе LLVM 3.0 в Xcode 4.2 вы можете подавить предупреждение следующим образом:
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[object performSelector:action];
#pragma clang diagnostic pop
Спасибо Скотту Томпсону (об этом подобном вопросе: performSelector может вызвать утечку, потому что его селектор неизвестен) для ответа.
Ответ 2
Поскольку вы динамически назначаете action
, компилятор видит возможную утечку с помощью ARC. В будущем компилятор LLVM может позволить вам подавить предупреждение. До тех пор вы можете избежать предупреждения, используя время выполнения objc_msgSend()
вместо -performSelector:
.
Сначала импортируйте заголовок сообщения времени выполнения
#import <objc/message.h>
Затем замените performSelector:
на objc_msgSend()
// [object performSelector:action];
objc_msgSend(object, action);
Ответ 3
Если вы пишете новый код, лучшим способом обработки обратных вызовов является использование блоков; они являются более безопасными и более гибкими, чем performSelector. См. http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/Blocks/Articles/00_Introduction.html.
Ответ 4
Я использую это:
[object tryToPerform:action with:nil];