Fehler: Die beschreibbare atomare Eigenschaft kann einen synthetisierten Setter / Getter nicht mit einem benutzerdefinierten Setter / Getter koppeln

128

Ich habe kürzlich versucht, ein älteres Xcode-Projekt zu kompilieren (das früher einwandfrei kompiliert wurde), und jetzt sehe ich viele Fehler in dieser Form:

error: writable atomic property 'someProperty' cannot pair a synthesized setter/getter with a user defined setter/getter

Das Codemuster, das diese Fehler verursacht, sieht immer so aus:

// Interface:

@property (retain) NSObject * someProperty;

// Implementation:

@synthesize someProperty; // to provide the getter
- (void)setSomeProperty:(NSObject *)newValue
{
    //..
}

Ich kann sehen, warum der Fehler generiert wird. Ich fordere den Compiler auf, meine Eigenschafts-Accessoren (sowohl Getter als auch Setter) zu synthetisieren, und überschreibe den Setter unmittelbar danach manuell. Dieser Code hat immer ein wenig gerochen.

Also, was ist der richtige Weg, um dies zu tun? Wenn ich @dynamicanstelle von verwende @synthesize, muss ich auch den Getter schreiben. Ist das der einzige Weg?

James
quelle
Kommt das nur bei atomicEigenschaften vor? Bei atomaren Eigenschaften ist es möglicherweise eine gute Idee, das Getter / Setter-Paar in Bezug auf die Sperrstrategie synchron zu halten. Dies ist schwierig, wenn ein Teil synthetisiert wird, während der andere benutzerdefinierter Code ist.
Nikolai Ruhe
Es geht sicherlich weg, wenn ich die Eigenschaft nichtatomar mache. Interessant. Ich hatte nicht einmal über das Synchronisationsproblem nachgedacht.
e.James
Ich habe dieses Thema besucht, um eine Lösung für genau dieses Problem zu finden. Ich möchte nicht wirklich selbst einen Getter und einen Setter schreiben. Na
ja
Standardmäßig ist jede Eigenschaft atomar und wir müssen sie explizit nichtatomar machen. Atomic-Eigenschaften sind threadsicher, daher können wir Setter und Getter für sie nicht implementieren, da dadurch die thread-sichere Funktionalität geändert wird. Ich hoffe, Sie bekommen den Grund, warum Sie diesen Fehler bekommen.
Mohd Haider

Antworten:

218

Ich hatte das gleiche Problem und nach ein wenig Recherche ist hier meine Schlussfolgerung zu diesem Thema:

Der Compiler warnt Sie vor einem @property, den Sie als atomar deklariert haben (dh indem Sie das nonatomicSchlüsselwort weglassen ). Sie bieten jedoch eine unvollständige Implementierung zum Synchronisieren des Zugriffs auf diese Eigenschaft.

Um diese Warnung verschwinden zu lassen:

Wenn Sie a @propertyals atomar deklarieren , führen Sie einen der folgenden Schritte aus:

  • verwenden @dynamicoder;
  • benutze @synthesizeund behalte den synthetisierten Setter und Getter oder;
  • Bereitstellung einer manuellen Implementierung sowohl des Setters als auch des Getters (ohne Verwendung einer der oben genannten Anweisungen).

Wenn Sie das @propertymit deklarieren (nonatomic), können Sie manuelle und synthetisierte Implementierungen von Gettern und Setzern mischen.

Update: Ein Hinweis zur automatischen Eigenschaftssynthese

Ab LLVM 4.0 bietet CLang eine automatische Synthese für deklarierte Eigenschaften, die dies nicht sind @dynamic. Selbst wenn Sie das weglassen @synthesize, stellt der Compiler standardmäßig Getter- und Setter-Methoden für Sie bereit. Die Regel für atomare Eigenschaften ist jedoch immer noch dieselbe: Entweder lassen Sie den Compiler sowohl den Getter als auch den Setter bereitstellen , oder implementieren Sie beide selbst!

Okty
quelle
Vielen Dank! "deklariere die @ Eigenschaft mit (nichtatomar)"
Nianliang
14

Sie müssen den Getter auch implementieren. Beispiel:

// Interface:

@property (retain) NSObject * someProperty;

// Implementation:

- (void)setSomeProperty:(NSObject *)newValue
{
    @synchronized (self)
    {
        // ...
    }
}

- (NSObject *)someProperty
{
    NSObject *ret = nil;

    @synchronized (self)
    {
        ret = [[someProperty retain] autorelease];
    }

    return ret;
}
Arturgrigor
quelle
12

Diese Frage wird neben den anderen Top-Treffern, die Sie bei der Suche nach "benutzerdefinierten Eigenschaften für Ziel C" erhalten, nicht mit Informationen zu "setter =" oder "getter =" aktualisiert.

Um weitere Informationen zu dieser Frage zu erhalten:

Sie können den Aufruf von @property mit Ihrer eigenen Methode versehen, indem Sie schreiben

    @property(setter = MySetterMethod:, getter = MyGetterMethod)

Beachten Sie den Doppelpunkt für die mitgelieferte Setter-Methode.

Referenz Apple-Dokumentation

EDIT: Ich bin mir nicht ganz sicher, wie die neuen Änderungen an den Eigenschaften von Objective-C (sie sind jetzt viel intelligenter) die Antworten auf diese Frage ändern. Vielleicht sollte alles als veraltet markiert sein.

Matias Forbord
quelle
Ich fand, dass das Einstellen der Setter-Methode die Warnung nicht wirklich entfernte. zB -> "@property (zuweisen, setter = setDelegate :) id delegate;" In diesem Fall kann ich nur meinen eigenen Getter hinzufügen oder die nichtatomare Eigenschaft hinzufügen. Ich bin mir nicht sicher, ob ich das sollte, da ich den Delegaten selbst "atomar" setze, spielt es keine Rolle, die nichtatomare Eigenschaft zu haben oder so verstehe ich.
David van Dugteren
Interessant, David. In welcher "Version" von Objective-C ist dies (ich nehme an, die XCode-Version wäre hilfreicher)? Ich bin mir nicht sicher, wie sich die jüngsten Änderungen an Objective-C, insbesondere unter iOS 6, darauf auswirken.
Matias Forbord
0

Für andere, die diesen Fehler nicht aus dem beschriebenen OP-Grund erhalten, haben Sie wahrscheinlich das gleiche Problem wie ich:

Sie haben eine @ -Eigenschaft mit demselben Namen wie eine - () -Methode.

Etwas wie das:

@property UIView *mainView;

-(UIView *)mainView;
Albert Renshaw
quelle