J'ai déclaré une propriété en lecture seule dans mon interface en tant que telle:
@property (readonly, nonatomic, copy) NSString* eventDomain;
Peut-être que je ne comprends pas bien les propriétés, mais je pensais que lorsque vous le déclarez comme readonly
, vous pouvez utiliser le setter généré dans le .m
fichier implementation ( ), mais les entités externes ne peuvent pas changer la valeur. Cette question SO dit que c'est ce qui devrait arriver. C'est le comportement que je recherche. Cependant, lorsque vous essayez d'utiliser le setter standard ou la syntaxe dot pour définir à l' eventDomain
intérieur de ma méthode init, cela me donne une unrecognized selector sent to instance.
erreur. Bien sûr, je suis @synthesize
la propriété. Essayer de l'utiliser comme ceci:
// inside one of my init methods
[self setEventDomain:@"someString"]; // unrecognized selector sent to instance error
Alors ai-je mal compris la readonly
déclaration sur une propriété? Ou est-ce qu'il se passe autre chose?
.h
? Sinon, je ne vois pas comment cela exposerait un setter public. MerciEiko et d'autres ont donné des réponses correctes.
Voici un moyen plus simple: accédez directement à la variable de membre privé.
Exemple
Dans le fichier .h d'en-tête:
@property (strong, nonatomic, readonly) NSString* foo;
Dans le fichier .m d'implémentation:
Voilà, c'est tout ce dont vous avez besoin. Pas de chichi, pas de chichi.
Détails
À partir de Xcode 4.4 et LLVM Compiler 4.0 ( nouvelles fonctionnalités de Xcode 4.4 ), vous n'avez pas besoin de jouer avec les tâches abordées dans les autres réponses:
synthesize
mot cléAprès avoir déclaré une propriété
foo
, vous pouvez supposer Xcode a ajouté une variable de membre privé nommé par un préfixe de underscore:_foo
.Si la propriété a été déclarée
readwrite
, Xcode génère une méthode getter nomméefoo
et un setter nommésetFoo
. Ces méthodes sont appelées implicitement lorsque vous utilisez la notation par points (mon Object.myMethod). Si la propriété a été déclaréereadonly
, aucun setter n'est généré. Cela signifie que la variable de sauvegarde, nommée avec le trait de soulignement, n'est pas elle-même en lecture seule. Lesreadonly
moyens simplement qu'aucun mutateur a été synthétisé, et donc en utilisant la notation de points pour définir une valeur échoue avec une erreur du compilateur. La notation par points échoue car le compilateur vous empêche d'appeler une méthode (le setter) qui n'existe pas.Le moyen le plus simple consiste à accéder directement à la variable membre, nommée avec le trait de soulignement. Vous pouvez le faire même sans déclarer cette variable nommée par soulignement! Xcode insère cette déclaration dans le cadre du processus de construction / compilation, donc votre code compilé aura effectivement la déclaration de variable. Mais vous ne voyez jamais cette déclaration dans votre fichier de code source d'origine. Pas de magie, juste du sucre syntaxique .
L'utilisation
self->
est un moyen d'accéder à une variable membre de l'objet / de l'instance. Vous pourrez peut-être omettre cela et utiliser simplement le nom var. Mais je préfère utiliser la flèche auto + car cela rend mon code auto-documenté. Lorsque vous voyez le,self->_foo
vous savez sans ambiguïté qu'il_foo
s'agit d'une variable membre sur cette instance.Soit dit en passant, la discussion des avantages et des inconvénients des accesseurs de propriété par rapport à l' accès Ivar directe est exactement le genre de traitement réfléchi que vous allez lire dans le Dr Matt Neuberg de programmation iOS livre. J'ai trouvé très utile de lire et de relire.
la source
readonly
telle qu'aucune autre classe ne peut la définir.Une autre façon que j'ai trouvée de travailler avec les propriétés en lecture seule est d'utiliser @synthesize pour spécifier le magasin de stockage. Par exemple
Puis dans la mise en œuvre
Vos méthodes peuvent ensuite être définies
m_whatever
, car il s'agit d'une variable membre.Une autre chose intéressante que j'ai réalisée ces derniers jours est que vous pouvez créer des propriétés en lecture seule qui sont inscriptibles par des sous-classes comme celles-ci:
(dans le fichier d'en-tête)
Puis, dans la mise en œuvre
Il utilisera la déclaration dans le fichier d'en-tête, afin que les sous-classes puissent mettre à jour la valeur de la propriété, tout en conservant sa lecture seule.
Un peu malheureusement en termes de masquage et d'encapsulation des données.
la source
Voir Personnalisation des classes existantes dans la documentation iOS.
Les propriétés en lecture seule n'ont qu'une méthode getter. Vous pouvez toujours définir l'ivar de support directement dans la classe de la propriété ou en utilisant le codage de valeur de clé.
la source
Vous ne comprenez pas l'autre question. Dans cette question, il y a une extension de classe, déclarée ainsi:
C'est ce qui génère le setter uniquement visible dans l'implémentation de la classe. Ainsi, comme le dit Eiko, vous devez déclarer une extension de classe et remplacer la déclaration de propriété pour indiquer au compilateur de générer un setter uniquement dans la classe.
la source
La solution la plus courte est:
MyClass.h
MyClass.h
la source
Si une propriété est définie en lecture seule, cela signifie qu'il n'y aura effectivement pas de setter pouvant être utilisé soit en interne à la classe, soit en externe à partir d'autres classes. (c'est-à-dire: vous n'aurez un "getter" que si cela a du sens.)
D'après les sons de celui-ci, vous voulez une propriété de lecture / écriture normale qui est marquée comme privée, ce que vous pouvez obtenir en définissant la variable de classe comme privée dans votre fichier d'interface en tant que telle:
la source