Problème sémantique: le getter synthétisé de la propriété suit la convention de dénomination de Cocoa pour retourner les objets `` possédés ''

283

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

Voici mon code: .h

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

.m

@synthesize newTitle;

Quelqu'un a-t-il une idée de comment je pourrais résoudre ce problème? Merci!!

Noam
la source
J'ai eu une erreur très similaire "La propriété suit les conventions de dénomination de Cocoa pour retourner les objets" possédés "" La réponse ci-dessous de Bavarious semble également résoudre ce problème.
TMin

Réponses:

606

Je suppose que la version du compilateur que vous utilisez suit également les règles de gestion de la mémoire pour les propriétés déclarées - plus spécifiquement, pour les accesseurs des propriétés déclarées:

Vous vous appropriez 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, lorsqu'elle est synthétisée, produit une méthode appelée -newTitle, d'où l'avertissement / l'erreur. -newTitleest censé être une méthode getter pour la newTitlepropriété, mais les conventions de dénomination stipulent qu'une méthode dont le nom commence parnew retourne un objet appartenant à l'appelant, ce qui n'est pas le cas des méthodes getter.

Vous pouvez résoudre ce problème 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 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 nonefamille de méthodes, par opposition à la newfamille de méthodes:

    #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à la fois le nom de la propriété et le nom du getter, avoir une méthode appelée -newTitlequi ne retourne pas un objet appartenant à l'appelant peut être déroutant pour les autres personnes qui lisent votre code.


Pour mémoire, Apple a publié Transitioning to ARC Release Notes , dans lequel ils déclarent:

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

Ils ont déjà été informés que leur déclaration n'est pas tout à fait exacte: le coupable est le nom de la méthode getter, pas le nom de la propriété.


Edit 17 janvier 2015: Je viens de remarquer un récent commit à Clang qui suggère l'option 3 ci-dessus (en utilisant objc_method_family(none)), y compris un correctif, pour 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 à terme.

Cœur
la source
6
A travaillé comme un homme de charme !! Merci!!! Pour référence future - j'ai utilisé "@property (strong, nonatomic, getter = theNewTitle) NSString * newTitle;"
Noam
8
Magnifique réponse. J'avais des variables préfixées "nouveau".
J'ai aussi ce problème et ça me fait perdre beaucoup de temps! Tu es vraiment un génie ~ Merci!
H Lai
NS_RETURNS_NOT_RETAINEDc'est aussi ce dont vous avez besoin.
DawnSong
55

Noms d'objets inacceptables

  • newButton
  • copyLabel
  • allocTitle

Noms d'objets acceptables

  • neueButton
  • mCopyLabel
  • _allocTitle

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

** ÉDITER **

Apparemment, vous ne pouvez pas non plus utiliser mutableCopy .

Jacksonkr
la source
1
J'ai également remarqué que la «copie» ne peut pas être utilisée pour l'instant.
Rishab
30

Le nom du membre commençant par new est ce qui déclenche l'avertissement. Remplacez le nom par le titre édité et l'avertissement disparaîtra. Je n'ai pas pu trouver de documentation confirmant cela, mais grâce aux tests, j'ai pu déterminer que les variables membres commençant par «nouveau» aggravent le compilateur.

Michael
la source
8

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;
sooop
la source
6

Cela ne ressemble pas à ce que Bavarious suggérait comme 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é. Auparavant, nous devions déclarer la variable et la propriété d'instance. Pas plus.

Maintenant, je crois que la bonne façon de procéder 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 de la propriété newTitleest synthétisée. Vous ne voulez pas que votre variable d'instance soit la même que votre propriété - trop facile de faire des erreurs .

Voir Exemple: Déclaration de propriétés et synthèse d'accesseurs

aquraishi
la source
Cela dépend de la version du compilateur. Les versions récentes de clang émettent un avertissement dans ce cas, c'est pourquoi j'ai mentionné la version du compilateur dans ma réponse.
Je ne pense pas que vous ayez résolu le problème. Pour Xcode 9, c'est une erreur, pas un avertissement. NS_RETURNS_NOT_RETAINEDest ce dont vous avez besoin.
DawnSong
4

Dans CoreData, si vous utilisez "new ..." dans l'attribut (compiler normalement), il se bloquera aléatoirement avec une exception "mauvais accès".

Il n'y a pas de journal de plantage et la ligne affichée avec le «point d'arrêt Toutes les exceptions» ne vous aidera pas du tout.

Las
la source
3

L'écriture manuelle d'un setter avec le nom identique à celui de la propriété a supprimé cet avertissement.

Serge Rykovski
la source
Dans Xcode 7.3, cela n'a pas aidé. Une erreur apparaît toujours sur la ligne de définition de propriété.
arlomedia
1

Outre le problème que vous devez / ne pouvez pas utiliser "nouveau" devant vos noms de propriété, disons encore une chose: essayez d'éviter "nouveau" devant les noms en général. "Nouveau" dépend du temps. Actuellement, c'est nouveau pour vous, mais quelque temps plus tard, vous voudrez peut-être implémenter à nouveau quelque chose de nouveau. Donc, utiliser "nouveau" dans les noms est toujours mauvais. Essayez de penser de cette façon: 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.

Encore une chose: essayez de nommer les fonctions et les méthodes avec le verbe en premier, comme setSomething ou getSomething. Mais dans les propriétés, essayez d'abord de nommer l'objet, comme heightMinimum, heightMaximum, etc. -> lorsque vous utilisez votre inspecteur lorsque vous codez, vous recherchez toujours des objets. Essaye le. ;-)

Philipp Schaller
la source
1

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

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

Nous pouvons 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 retourné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 qui est fonctionnellement équivalente à celle illustrée ci-dessous.

Joignez plus de détails ici.

DawnSong
la source
-2

essaye ça:-

@property (nonatomic,retain) NSString *newTitle;
Gypsa
la source
1
Toujours le même problème. Pour info, la ligne d'erreur est sur la ligne @synthesize.
Noam