web-dev-qa-db-fra.com

Problème sémantique: le getter synthétisé de la propriété suit la convention de nommage Cocoa pour le retour des objets 'possédés'

J'utilise actuellement le SDK iOS 5 pour développer mon application. J'essaie de transformer une propriété NSString en propriété, puis de la synthétiser dans le fichier .m (je l'avais déjà fait auparavant sans problème). Je suis tombé sur ceci: "Problème sémantique: le getter synthétisé de Property suit la convention de nommage Cocoa pour le retour des objets" possédés "."

Ceci est mon code: .h

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

.m

@synthesize newTitle;

Quelqu'un at-il une idée de la façon dont je pourrais résoudre ce problème? Merci!!

281
Noam

J’imagine que la version du compilateur que vous utilisez suit les règles de gestion de la mémoire pour les propriétés déclarées, et plus précisément pour les accesseurs des propriétés déclarées:

Vous devenez propriétaire d'un objet si vous le créez à l'aide d'une méthode dont le nom commence par "alloc", "new", "copy" ou "mutableCopy".

Une propriété nommée newTitle, une fois synthétisée, donne une méthode appelée -newTitle, d'où l'avertissement/l'erreur. -newTitle est censé être une méthode de lecture pour la propriété newTitle, mais les conventions de dénomination stipulent qu'une méthode dont le nom commence par new renvoie un objet appartenant à l'appelant, qui n'est pas le cas de méthodes getter.

Vous pouvez résoudre ceci en:

  1. Renommer cette propriété:

    @property (strong, nonatomic) NSString *theNewTitle;
    
  2. Conserver le nom de la propriété et spécifier un nom de getter qui ne commence pas par l’un des préfixes de nom de méthode spéciaux:

    @property (strong, nonatomic, getter=theNewTitle) NSString *newTitle;
    
  3. Conserver à la fois le nom de la propriété et le nom du getter et indiquer au compilateur que, même si le nom du getter commence par new, il appartient à la famille de méthodes none par opposition à la méthode new famille:

    #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
    

    Notez que même si cette solution vous permet de conserver newTitle comme nom de propriété et d’obtention, le fait d’avoir une méthode appelée -newTitle qui ne renvoie pas un objet appartenant à l’appelant peut être déroutant pour d’autres. les gens lisent votre code.


Pour mémoire, Apple ont publié Transition vers les notes de publication ARC , dans lequel ils indiquent:

Vous ne pouvez pas donner à une propriété un nom commençant par new ou copy.

Ils ont déjà été informés que leur déclaration n’est pas très précise: le coupable est le nom de la méthode de lecture, pas le nom de la propriété.


Edit 17 Jan 2015: Je viens de remarquer un récent commit sur Clang qui suggère l'option 3 ci-dessus (en utilisant objc_method_family(none)), y compris un correctif, dans le cas général où un nom de propriété correspond à l'un des préfixes de famille de méthodes spéciales. Xcode incorporera probablement ce changement éventuellement.

603
user557219

Noms d'objets inacceptables

  • nouveauButton
  • copyLabel
  • allocTitle

Noms d'objets acceptables

  • neueButton
  • mCopyLabel
  • _allocTitle

#arc # synthétisé automatiquement # xcode-4.6.1

** MODIFIER **

Apparemment, vous ne pouvez pas utiliser mutableCopy non plus.

51
Jacksonkr

Le nom du membre commençant par new est ce qui déclenche l'avertissement. Changez le nom en editedTitle et l'avertissement disparaîtra. J'étais incapable de trouver de la documentation confirmant cela, mais grâce à des tests, nous avons pu déterminer que les variables membres commençant par "new" aggravaient le compilateur.

30
Michael

ARC ne permet pas d'utiliser "Nouveau ...." dans le nom de la propriété. mais vous pouvez utiliser "newTitle" en changeant le nom du getter.

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

Il ne semble pas que Bavario suggère ce que vous vouliez faire. Tout ce que vous voulez faire est de déclarer une variable d'instance NewTitle puis de synthétiser la propriété. Nous avions l'habitude de déclarer la variable d'instance et la propriété. Pas plus.

Maintenant, je crois que la bonne façon de faire est la suivante:

.h

@interface ViewController : UIViewController

@property (nonatomic, strong) NSString *newTitle;

.m

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

La variable d'instance pour la propriété newTitle est synthétisée. Vous ne voulez pas que votre variable d'instance soit identique à votre propriété - trop facile de faire des erreurs .

Voir Exemple: déclaration des propriétés et synthèse des accesseurs

6
aquraishi

Dans CoreData, si vous utilisez "new ..." dans l'attribut (compiler normalement), il se plantera de manière aléatoire avec une exception "bad access".

Il n'y a pas de journal des collisions et la ligne indiquée avec le "Point d'arrêt toutes les exceptions" ne vous aidera pas du tout.

4
las

L'écriture manuelle d'un setter avec le même nom que celui de la propriété a supprimé cet avertissement.

3
Serge Rykovski

Outre le problème que vous devriez/ne pouvez pas utiliser "nouveau" devant vos noms de propriété, laissez une dernière chose à dire: essayez d'éviter "nouveau" devant des noms en général. "Nouveau" dépend du temps. Actuellement, il est nouveau pour vous, mais vous voudrez peut-être implémenter quelque chose de nouveau un peu plus tard. Donc, utiliser "nouveau" dans les noms est toujours mauvais. Essayez de penser ainsi: dans le monde de la programmation, "nouveau" crée toujours quelque chose: une nouvelle instance de quelque chose.

Dans votre cas, lorsque vous souhaitez attribuer un titre différent, puis le nom actuel de votre propriété titleReplacement.

Une dernière chose: essayez de nommer d’abord les fonctions et les méthodes avec le verbe, comme setSomething ou getSomething. Mais dans les propriétés, essayez de nommer l’objet d’abord, comme heightMinimum, heightMaximum, etc. -> lorsque vous utilisez votre inspecteur pour coder, vous recherchez toujours des objets. Essaye le. ;-)

1
Philipp Schaller

NS_RETURNS_NOT_RETAINED est utilisé pour résoudre le problème de nommage.

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

On peut trouver sa définition comme suit,

#define NS_RETURNS_NOT_RETAINED __attribute__((ns_returns_not_retained))

L'attribut 'ns_returns_not_retained' est le complément de 'ns_returns_retained'. Lorsqu'une fonction ou une méthode peut sembler obéir aux conventions Cocoa et renvoyer un objet Cocoa conservé, cet attribut peut être utilisé pour indiquer que la référence d'objet renvoyée ne doit pas être considérée comme une référence "propriétaire" renvoyée à l'appelant. Le framework Foundation définit une macro NS_RETURNS_NOT_RETAINED fonctionnellement équivalente à celle présentée ci-dessous.

Joindre plus de détails ici.

1
DawnSong