Semantisches Problem: Der synthetisierte Getter von Property folgt der Cocoa-Namenskonvention für die Rückgabe von "eigenen" Objekten

283

Ich verwende derzeit das iOS 5 SDK, um meine App zu entwickeln. Ich versuche, einen NSString zu einer Eigenschaft zu machen und ihn dann in der .m-Datei zu synthetisieren (ich habe dies zuvor ohne Probleme getan). Nun stieß ich auf Folgendes: "Semantisches Problem: Der synthetisierte Getter von Property folgt der Kakao-Namenskonvention für die Rückgabe von 'eigenen' Objekten."

Dies ist mein Code: .h

@interface ViewController : UIViewController {
     NSString *newTitle;
}
@property (strong, nonatomic) NSString *newTitle;

.m

@synthesize newTitle;

Hat jemand eine Ahnung, wie ich das beheben könnte? Vielen Dank!!

Noam
quelle
Ich hatte einen sehr ähnlichen Fehler: "Eigenschaft folgt den Kakao-Namenskonventionen für die Rückgabe von" eigenen "Objekten." Bavarious 'Antwort unten scheint dies ebenfalls zu lösen.
TMin

Antworten:

606

Ich vermute, dass die von Ihnen verwendete Compilerversion auch für deklarierte Eigenschaften den Speicherverwaltungsregeln folgt - insbesondere für die Accessoren der deklarierten Eigenschaften:

Sie übernehmen das Eigentum an einem Objekt, wenn Sie es mit einer Methode erstellen, deren Name mit "alloc", "new", "copy" oder "mutableCopy" beginnt.

Eine Eigenschaft mit dem Namen newTitleergibt bei der Synthese eine aufgerufene Methode -newTitle, daher die Warnung / der Fehler. -newTitlesoll eine Getter-Methode für die newTitleEigenschaft sein, Namenskonventionen besagen jedoch, dass eine Methode, deren Name mit beginnt, newein Objekt zurückgibt, das dem Aufrufer gehört, was bei Getter-Methoden nicht der Fall ist.

Sie können dies lösen durch:

  1. Umbenennen dieser Eigenschaft:

    @property (strong, nonatomic) NSString *theNewTitle;
  2. Behalten Sie den Eigenschaftsnamen bei und geben Sie einen Getter-Namen an, der nicht mit einem der speziellen Präfixe für Methodennamen beginnt:

    @property (strong, nonatomic, getter=theNewTitle) NSString *newTitle;
  3. Behalten Sie sowohl den Eigenschaftsnamen als auch den Getter-Namen bei und teilen Sie dem Compiler mit, dass der Getter-Name, obwohl er mit beginnt new, zur noneMethodenfamilie und nicht zur newMethodenfamilie gehört:

    #ifndef __has_attribute
    #define __has_attribute(x) 0  // Compatibility with non-clang compilers
    #endif
    
    #if __has_attribute(objc_method_family)
    #define BV_OBJC_METHOD_FAMILY_NONE __attribute__((objc_method_family(none)))
    #else
    #define BV_OBJC_METHOD_FAMILY_NONE
    #endif
    
    @interface ViewController : UIViewController
    @property (strong, nonatomic) NSString *newTitle;
    - (NSString *)newTitle BV_OBJC_METHOD_FAMILY_NONE;
    @end

    Beachten Sie, dass, obwohl Sie mit dieser Lösung newTitlesowohl den Eigenschaftsnamen als auch den Getter-Namen beibehalten können, eine Methode namens -newTitle, die kein Objekt zurückgibt, das dem Aufrufer gehört, für andere Personen, die Ihren Code lesen, verwirrend sein kann.


Apple hat Transitioning to ARC Release Notes veröffentlicht , in denen Folgendes angegeben ist:

Sie können einer Eigenschaft keinen Namen geben, der mit newoder beginnt copy.

Sie wurden bereits darüber informiert, dass ihre Aussage nicht ganz korrekt ist: Der Schuldige ist der Name der Getter-Methode, nicht der Name der Eigenschaft.


Bearbeiten 17. Januar 2015: Ich habe kürzlich ein Commit für Clang bemerkt , das Option 3 oben (unter Verwendung objc_method_family(none)) einschließlich eines Fix-it für den allgemeinen Fall vorschlägt , in dem ein Eigenschaftsname mit einem der Präfixe der speziellen Methodenfamilie übereinstimmt. Xcode wird diese Änderung wahrscheinlich irgendwann übernehmen.

Cœur
quelle
6
Arbeitete wie ein Zaubermann !! Vielen Dank!!! Als zukünftige Referenz - ich habe "@property (stark, nichtatomar, getter = theNewTitle) NSString * newTitle;"
Noam
8
Wunderbare Antwort. Ich hatte Variablen mit dem Präfix "neu".
Ich habe auch dieses Problem und es verschwendet meine viel Zeit! Du bist wirklich ein Genie ~ Danke!
H Lai
NS_RETURNS_NOT_RETAINEDist was du auch brauchst.
DawnSong
55

Inakzeptable Objektnamen

  • newButton
  • copyLabel
  • allocTitle

Akzeptable Objektnamen

  • neuerButton
  • mCopyLabel
  • _allocTitle

#arc # automatisch synthetisiert # xcode-4.6.1

** BEARBEITEN **

Anscheinend können Sie mutableCopy auch nicht verwenden .

Jacksonkr
quelle
1
Mir ist auch aufgefallen, dass "Kopie" derzeit nicht verwendet werden kann.
Rishab
30

Der Name des Mitglieds, das mit new beginnt, löst die Warnung aus. Ändern Sie den Namen in editierter Titel und die Warnung wird ausgeblendet. Ich konnte keine Dokumentation finden, die dies bestätigt, aber durch Testen konnte festgestellt werden, dass Mitgliedsvariablen, die mit 'neu' beginnen, den Compiler erschweren.

Michael
quelle
8

ARC erlaubt nicht, "Neu ...." im Eigenschaftsnamen zu verwenden. Sie können jedoch "newTitle" verwenden, indem Sie den Getter-Namen ändern.

@property (nonatomic, strong, getter=theNewTitle) NSString *newTitle;
sooop
quelle
6

Es sieht nicht so aus, als ob Bavarious vorgeschlagen hätte, was Sie tun wollten. Sie möchten lediglich eine Instanzvariable deklarieren NewTitleund dann die Eigenschaft synthetisieren. Früher mussten wir die Instanzvariable und die Eigenschaft deklarieren. Nicht mehr.

Ich glaube, der richtige Weg, dies zu tun, ist der folgende:

.h

@interface ViewController : UIViewController

@property (nonatomic, strong) NSString *newTitle;

.m

@synthesize newTitle = _newTitle; // Use instance variable _newTitle for storage

Die Instanzvariable für die Eigenschaft newTitlewird synthetisiert. Sie möchten nicht, dass Ihre Instanzvariable mit Ihrer Eigenschaft übereinstimmt - zu leicht, um Fehler zu machen .

Siehe Beispiel: Eigenschaften deklarieren und Accessoren synthetisieren

Aquraishi
quelle
Das hängt von der Compilerversion ab. Neuere Versionen von clang geben in diesem Fall eine Warnung aus, weshalb ich in meiner Antwort die Compilerversion erwähnt habe.
Ich glaube nicht, dass Sie das Problem gelöst haben. Für Xcode 9 ist es ein Fehler, keine Warnung. NS_RETURNS_NOT_RETAINEDist was du brauchst.
DawnSong
4

Wenn Sie in CoreData das Attribut "new ..." verwenden (normalerweise kompilieren), stürzt es zufällig mit der Ausnahme "bad access" ab.

Es gibt kein Absturzprotokoll und die Zeile mit dem Haltepunkt "Alle Ausnahmen" hilft Ihnen überhaupt nicht.

las
quelle
3

Durch manuelles Schreiben eines Setters mit demselben Namen wie der Eigenschaft wurde diese Warnung entfernt.

Serge Rykovski
quelle
In Xcode 7.3 hat dies nicht geholfen. In der Eigenschaftsdefinitionszeile wird weiterhin ein Fehler angezeigt.
Arlomedia
1

Neben dem Problem, dass Sie "neu" vor Ihren Eigenschaftsnamen verwenden sollten / können, sagen wir noch eines: Versuchen Sie, "neu" vor Namen im Allgemeinen zu vermeiden. "Neu" ist zeitabhängig. Derzeit ist es neu für Sie, aber einige Zeit später möchten Sie vielleicht wieder etwas Neues implementieren. Die Verwendung von "neu" in Namen ist also immer schlecht. Versuchen Sie so zu denken: In der Programmierwelt schafft "neu" immer etwas: eine neue Instanz von etwas.

In Ihrem Fall, wenn Sie einen anderen Titel als den aktuellen Namen Ihrer Eigenschaft titleReplacement zuweisen möchten.

Noch etwas: Versuchen Sie, Funktionen und Methoden zuerst mit dem Verb zu benennen, z. B. setSomething oder getSomething. Versuchen Sie jedoch in Eigenschaften, das Objekt zuerst zu benennen, z. B. heightMinimum, heightMaximum usw. -> Wenn Sie beim Codieren Ihren Inspektor verwenden, suchen Sie immer nach Objekten. Versuch es. ;-);

Philipp Schaller
quelle
1

NS_RETURNS_NOT_RETAINED wird verwendet, um das Namensproblem zu lösen.

@property (nonatomic, copy) NSString *newTitle NS_RETURNS_NOT_RETAINED;

Wir können seine Definition wie folgt finden:

#define NS_RETURNS_NOT_RETAINED __attribute__((ns_returns_not_retained))

Das Attribut 'ns_returns_not_retained' ist das Komplement von 'ns_returns_retained'. Wenn eine Funktion oder Methode den Cocoa-Konventionen zu entsprechen scheint und ein beibehaltenes Cocoa-Objekt zurückgibt, kann dieses Attribut verwendet werden, um anzugeben, dass die zurückgegebene Objektreferenz nicht als "besitzende" Referenz betrachtet werden sollte, die an den Aufrufer zurückgegeben wird. Das Foundation-Framework definiert ein Makro NS_RETURNS_NOT_RETAINED, das funktional dem unten gezeigten entspricht.

Weitere Details hier anhängen .

DawnSong
quelle
-2

Versuche dies:-

@property (nonatomic,retain) NSString *newTitle;
Gypsa
quelle
1
Trotzdem das gleiche genaue Problem. Zu Ihrer Information, die Fehlerzeile befindet sich in der Zeile @synthesize.
Noam