wake-up-neo.com

Semantisches Problem: Der synthetisierte Getter der Eigenschaft folgt der Cocoa-Namenskonvention für die Rückgabe von Objekten im Besitz

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). Jetzt stieß ich auf Folgendes: "Semantisches Problem: Der synthetisierte Getter von Property folgt der Cocoa-Namenskonvention für die Rückgabe von Objekten im Besitz."

Das 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!!

281
Noam

Ich vermute, dass die von Ihnen verwendete Compilerversion auch für deklarierte Eigenschaften - genauer gesagt für Accessoren deklarierter Eigenschaften - die Speicherverwaltungsregeln lautet:

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 newTitle liefert bei der Synthese eine Methode mit dem Namen _-newTitle_, daher die Warnung/der Fehler. _-newTitle_ soll eine Getter-Methode für die Eigenschaft newTitle sein. Die Namenskonventionen besagen jedoch, dass eine Methode, deren Name mit new beginnt, ein Objekt zurückgibt, dessen Eigentümer der Aufrufer ist, was bei Getter-Methoden nicht der Fall ist.

Sie können dies lösen, indem Sie:

  1. Diese Eigenschaft umbenennen:

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

    _@property (strong, nonatomic, getter=theNewTitle) NSString *newTitle;
    _
  3. Behalten Sie sowohl den Eigenschaftsnamen als auch den Getternamen bei und teilen Sie dem Compiler mit, dass der Gettername, obwohl er mit new beginnt, im Gegensatz zur Methodenfamilie none zur Methodenfamilie new 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 newTitle sowohl als Eigenschaftsname als auch als Gettername beibehalten können, eine Methode mit dem Namen _-newTitle_, die kein Objekt zurückgibt, dessen Eigentümer der Aufrufer ist, für andere Personen, die Ihren Code lesen, verwirrend sein kann .


Für den Datensatz haben Apple veröffentlicht Übergang zu ARC Release Notes , in denen sie angeben:

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

Ihnen wurde bereits mitgeteilt, dass ihre Aussage nicht ganz korrekt ist: Der Schuldige ist der Name der Getter-Methode, nicht der Name der Eigenschaft.


Edit 17 Jan 2015: Ich habe gerade ein Commit für Clang bemerkt, das Option 3 oben vorschlägt (Verwenden von objc_method_family(none)), einschließlich eines Fix-It, für den allgemeinen Fall, dass ein Eigenschaftsname mit einem der speziellen Präfixe der Methodenfamilie übereinstimmt. Xcode wird diese Änderung wahrscheinlich irgendwann übernehmen.

603
user557219

Inakzeptable Objektnamen

  • newButton
  • copyLabel
  • allocTitle

Akzeptable Objektnamen

  • neueButton
  • mCopyLabel
  • _allocTitle

#arc # automatisch synthetisiert # xcode-4.6.1

** EDIT **

Anscheinend können Sie mutableCopy auch nicht verwenden.

51
Jacksonkr

Der Name des Mitglieds, der mit new beginnt, löst die Warnung aus. Ändern Sie den Namen in editedTitle und die Warnung verschwindet. Ich konnte keine Dokumentation finden, die dies bestätigt, konnte aber durch Testen feststellen, dass Membervariablen, die mit "new" beginnen, den Compiler erschweren.

30
Michael

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

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

Es sieht nicht so aus, als ob Bavarious das vorgeschlagen hätte, was Sie tun wollten. Sie möchten lediglich eine Instanzvariable NewTitle deklarieren und dann die Eigenschaft synthetisieren. Früher mussten die Instanzvariable und die Eigenschaft deklariert werden. 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 newTitle wird synthetisiert. Sie möchten nicht, dass Ihre Instanzvariable mit Ihrer Eigenschaft übereinstimmt - zu leicht, um Fehler zu machen .

Siehe Beispiel: Deklarieren von Eigenschaften und Synthetisieren von Accessoren

6
aquraishi

Wenn Sie in CoreData im Attribut "new ..." verwenden (normalerweise kompilieren), stürzt es mit der Ausnahme "bad access" nach dem Zufallsprinzip ab.

Es gibt kein Absturzprotokoll und die mit "All Exceptions Breakpoint" angezeigte Zeile hilft Ihnen überhaupt nicht.

4
las

Wenn Sie einen Setter manuell mit demselben Namen wie die Eigenschaft schreiben, wird diese Warnung entfernt.

3
Serge Rykovski

Abgesehen von dem Problem, dass Sie "new" vor Ihren Eigenschaftsnamen verwenden sollten/können, sagen wir noch eines: Versuchen Sie, "new" vor Namen im Allgemeinen zu vermeiden. "Neu" ist zeitabhängig. Derzeit ist es für Sie neu, aber einige Zeit später möchten Sie möglicherweise wieder etwas Neues implementieren. Die Verwendung von "new" 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.

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

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 sein 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 soll, die an den Aufrufer zurückgegeben wird. Das Foundation-Framework definiert ein Makro NS_RETURNS_NOT_RETAINED, das funktional dem unten gezeigten entspricht.

Fügen Sie weitere Details hier hinzu.

1
DawnSong