2010-04-29 8 views
22

J'essayais de créer une propriété en lecture seule. Je voulais initialiser avec une valeur de la classe créant une instance de cette classe, par ex.Initialisation d'une propriété readonly

@property (retain,readonly) NSString *firstName;

Et j'ai essayé de l'initialiser comme ceci:

-(id)initWithName:(NSString *)n{ self.firstName = n; }

Une fois que je l'ai fait, le compilateur a signalé une erreur qui ne peut être attribué la propriété en lecture seule. Alors, comment puis-je faire cela?

Répondre

13

Ne pas utiliser le setter synthétisé:

firstName = [n retain]; //Or copy 

Il est généralement conseillé de contourner les setters dans toutes les méthodes d'initialisation et dealloc de toute façon.

+0

Le problème avec mon implémentation ci-dessus est que la valeur n'est pas conservée. Une fois que j'ajoute le retain à la propriété, cette affectation va-t-elle définir la valeur dans la propriété. Et si un autre objet accède à cette propriété, cette valeur sera là. J'ai aussi modifié ma question. – awsome

+0

Pourquoi est-ce que ce serait un problème? Utiliser 'firstname = [n retain]' ne fera que rendre un firstName à 'n'. Alors oui, quand un autre objet accède à cette propriété, la valeur sera là. :) – Rengers

+0

Si j'essaie de le faire de cette façon si j'accède à cette propriété, je reçois l'exception suivante. Signal reçu du programme: "EXC_BAD_ACCESS". Et cette erreur n'est due à aucune autre propriété. J'ai beaucoup étudié cela dans le débogueur. Cette propriété indique "hors de portée". Et si je l'assigne avec, self.firstName = n;. alors tout fonctionne bien. – awsome

38

Affectez directement à la variable d'instance (n'oubliez pas d'ajouter un retain ou copy si vous en avez besoin) ou redéfinissez la propriété dans une extension de classe privée. Comme ceci:

Dans votre fichier .h:

@property (readonly, copy) NSString *firstName; 

Dans votre fichier .m:

@interface MyClass() 

// Redeclare property as readwrite 
@property (readwrite, copy) NSString *firstName; 

@end 


@implementation MyClass 

@synthesize firstName; 
... 

Maintenant, vous pouvez utiliser le setter synthétisé dans votre implémentation, mais l'interface de classe montre toujours la propriété en lecture seule. Notez que les autres classes qui importent votre fichier .h peuvent toujours appeler -[MyClass setFirstName:] mais ils ne sauront pas qu'il existe et recevront un avertissement du compilateur.

+0

Cela semble une bonne solution de contournement. Merci. – awsome

+0

Y a-t-il un avantage à utiliser le setter synthétisé par rapport à l'approche suggérée par @Renger? – Madbreaks

2

Vous pouvez accéder directement à la propriété avec:

_firstName = n;

La méthode setter que self.firstName = n ne sera pas implique d'synthétisés car vous avez spécifié readonly dans @property (retain,readonly) NSString *firstName;, d'où l'erreur du compilateur.

+0

il n'y a pas de _firstName ... –

+0

je crois comprendre que _firstName existera. C'est le ivar sous-jacent créé lorsque la propriété est déclarée. À partir de Xcode 4.6, le compilateur devrait automatiquement créer ceci pour vous. – Bob9630

+0

C'est aussi ce que je comprends @ Bob9630. Les autres réponses à cette question n'ont pas produit le résultat souhaité dans mon cas, alors que cela a été le cas. –

Questions connexes