1295 Stimmen

PerformSelector kann ein Leck verursachen, weil sein Selektor unbekannt ist.

Ich erhalte die folgende Warnung vom ARC-Compiler:

"performSelector kann ein Leck verursachen, weil sein Selektor unbekannt ist".

Das ist, was ich tue:

[_controller performSelector:NSSelectorFromString(@"someMethod")];

Warum erhalte ich diese Warnung? Ich verstehe, dass der Compiler nicht überprüfen kann, ob der Selektor existiert oder nicht, aber warum würde das ein Leck verursachen? Und wie kann ich meinen Code ändern, damit ich diese Warnung nicht mehr erhalte?

1188voto

Scott Thompson Punkte 21017

Im LLVM 3.0-Compiler in Xcode 4.2 können Sie die Warnung wie folgt unterdrücken:

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
    [self.ticketTarget performSelector: self.ticketAction withObject: self];
#pragma clang diagnostic pop

Wenn Sie den Fehler an mehreren Stellen erhalten und das C-Makrosystem verwenden möchten, um die pragmas zu verstecken, können Sie ein Makro definieren, um das Unterdrücken der Warnung zu erleichtern:

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

Sie können das Makro wie folgt verwenden:

SuppressPerformSelectorLeakWarning(
    [_target performSelector:_action withObject:self]
);

Wenn Sie das Ergebnis der ausgeführten Nachricht benötigen, können Sie Folgendes tun:

id result;
SuppressPerformSelectorLeakWarning(
    result = [_target performSelector:_action withObject:self]
);

208voto

sergio Punkte 68479

Meine Vermutung dazu ist folgende: Da dem Compiler der Selektor unbekannt ist, kann ARC keine ordnungsgemäße Speicherverwaltung durchsetzen.

Tatsächlich gibt es Zeiten, in denen die Speicherverwaltung durch eine spezifische Konvention mit dem Namen der Methode verbunden ist. Konkret denke ich an Bequemlichkeitskonstruktoren im Vergleich zu make-Methoden; Erstere geben konventionell ein freigegebenes Objekt zurück, letztere ein behaltenes Objekt. Die Konvention basiert auf den Namen des Selektors, daher kann der Compiler, falls er den Selektor nicht kennt, die ordnungsgemäße Speicherverwaltung nicht durchsetzen.

Wenn das korrekt ist, denke ich, dass du deinen Code sicher verwenden kannst, vorausgesetzt, du stellst sicher, dass alles in Bezug auf die Speicherverwaltung in Ordnung ist (zum Beispiel, dass deine Methoden keine Objekte zurückgeben, die sie allozieren).

121voto

0xced Punkte 23133

In Ihrem Projekt Build Settings unter Andere Warnungen (WARNING_CFLAGS), fügen Sie hinzu
-Wno-arc-performSelector-leaks

Stellen Sie jetzt sicher, dass der Selector, den Sie aufrufen, nicht dazu führt, dass Ihr Objekt beibehalten oder kopiert wird.

110voto

jluckyiv Punkte 3663

Als Workaround, bis der Compiler das Überschreiben der Warnung zulässt, können Sie die Laufzeit verwenden.

Sie benötigen den Header:

#import 

Versuchen Sie dann Folgendes:

// Für strenge Compiler.
((id(*)(id,SEL))objc_msgSend)(_controller, sel_getUid("someMethod"));

ODER

// Code des alten Antworten:
objc_msgSend(_controller, NSSelectorFromString(@"someMethod"));

Anstelle von:

[_controller performSelector:NSSelectorFromString(@"someMethod")];

88voto

Barlow Tucker Punkte 5799

Um den Fehler nur in der Datei mit dem perform-Selector zu ignorieren, fügen Sie eine #pragma wie folgt hinzu:

#pragma clang diagnostic ignored "-Warc-performSelector-leaks"

Dies würde die Warnung in dieser Zeile ignorieren, aber es weiterhin im Rest Ihres Projekts ermöglichen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X