erreur: la propriété atomique inscriptible ne peut pas associer un setter / getter synthétisé avec un setter / getter défini par l'utilisateur

128

J'ai récemment essayé de compiler un ancien projet Xcode (qui compilait très bien), et maintenant je vois beaucoup d'erreurs de cette forme:

error: writable atomic property 'someProperty' cannot pair a synthesized setter/getter with a user defined setter/getter

Le modèle de code qui provoque ces erreurs ressemble toujours à ceci:

// Interface:

@property (retain) NSObject * someProperty;

// Implementation:

@synthesize someProperty; // to provide the getter
- (void)setSomeProperty:(NSObject *)newValue
{
    //..
}

Je peux voir pourquoi l'erreur est générée. Je dis au compilateur de synthétiser mes accesseurs de propriété (getter et setter), puis immédiatement après je remplace le setter manuellement. Ce code a toujours senti un peu mauvais.

Alors, quelle est la bonne façon de faire cela? Si j'utilise à la @dynamicplace de @synthesize, je devrai également écrire le getter. Est-ce le seul moyen?

e.James
la source
Cela se produit-il uniquement avec les atomicpropriétés? Dans le cas de propriétés atomiques, il peut être judicieux de synchroniser la paire getter / setter en ce qui concerne la stratégie de verrouillage. Ceci est difficile si une partie est synthétisée tandis que l'autre est du code personnalisé.
Nikolai Ruhe
Cela disparaît certainement si je rends la propriété non atomique. Intéressant. Je n'avais même pas pensé au problème de la synchronisation.
e.James
J'ai visité ce sujet pour trouver une solution à ce problème exact. Je n'ai pas vraiment envie d'écrire un getter et un setter tout seul. Oh bien…
Constantino Tsarouhas
Par défaut, chaque propriété est atomique et nous devons les rendre non atomiques explicitement. Les propriétés atomiques sont thread-safe, nous ne pouvons donc pas implémenter setter et getter pour elles car cela changera sa fonctionnalité thread-safe. J'espère que vous obtenez la raison pour laquelle vous obtenez cette erreur.
Mohd Haider

Réponses:

218

J'ai eu le même problème et après avoir fait un peu de recherche, voici ma conclusion sur ce problème:

Le compilateur vous avertit de a @propertyque vous avez déclaré comme atomique (c'est-à-dire en omettant le nonatomicmot - clé), mais vous fournissez une implémentation incomplète de la façon de synchroniser l'accès à cette propriété.

Pour faire disparaître cet avertissement:

Si vous déclarez que a @propertyest atomique, effectuez l'une des opérations suivantes:

  • utiliser @dynamicou;
  • utiliser @synthesizeet conserver le setter et le getter synthétisés ou;
  • fournir une mise en oeuvre manuelle des deux le compositeur et le getter (sans utiliser l' une des directives ci - dessus).

Si vous déclarez le @propertyavec, (nonatomic)vous pouvez mélanger des implémentations manuelles et synthétisées des getters et des setters.

Mise à jour: une note sur l'auto-synthèse des propriétés

Depuis LLVM 4.0, CLang fournit une synthèse automatique pour les propriétés déclarées qui ne le sont pas @dynamic. Par défaut, même si vous omettez le @synthesize, le compilateur vous fournira les méthodes getter et setter. Toutefois, la règle des propriétés atomiques est toujours le même: soit laisser le compilateur fournir à la fois le getter et le setter ou les mettre en œuvre à la fois vous - même!

octy
la source
Merci! "déclarer la propriété @ avec (nonatomique)"
Nianliang
14

Vous devez également implémenter le getter. Exemple:

// Interface:

@property (retain) NSObject * someProperty;

// Implementation:

- (void)setSomeProperty:(NSObject *)newValue
{
    @synchronized (self)
    {
        // ...
    }
}

- (NSObject *)someProperty
{
    NSObject *ret = nil;

    @synchronized (self)
    {
        ret = [[someProperty retain] autorelease];
    }

    return ret;
}
arturgrigor
la source
12

Cette question, parmi les autres meilleurs résultats que vous obtenez en recherchant "propriété personnalisée de l'objectif C", n'est pas mise à jour avec des informations sur "setter =" ou "getter =".

Donc, pour fournir plus d'informations sur cette question:

Vous pouvez fournir l'appel @property avec votre propre méthode en écrivant

    @property(setter = MySetterMethod:, getter = MyGetterMethod)

Notez les deux points pour la méthode setter fournie.

Documentation de référence Apple

EDIT: Je ne sais pas trop comment les nouvelles modifications apportées aux propriétés d'Objective-C (elles sont beaucoup plus intelligentes maintenant) changent les réponses à cette question. Peut-être que tout devrait être marqué comme obsolète.

Matias Forbord
la source
J'ai trouvé que le réglage de la méthode setter ne supprimait pas réellement l'avertissement. par exemple -> "@property (assign, setter = setDelegate :) id délégué;" Dans ce cas, tout ce que je peux faire est d'ajouter mon propre getter ou d'ajouter la propriété non atomique, ce que je ne suis pas sûr de devoir faire, étant donné que je définis moi-même le délégué de manière `` atomique '', cela n'a pas d'importance d'avoir la propriété non atomique , ou alors je comprends.
David van Dugteren
Intéressant, David. Dans quelle "version" d'Objective-C se trouve-t-il (je suppose que dire que la version XCode serait plus utile)? Je ne sais pas ce que les récents changements apportés à Objective-C, en particulier avec iOS 6, affectent cela.
Matias Forbord
0

Pour les autres qui obtiennent cette erreur pas pour la raison décrite par OP, vous rencontrez probablement le même problème que moi:

Vous avez une propriété @ avec le même nom qu'une méthode - ().

Quelque chose comme ça:

@property UIView *mainView;

-(UIView *)mainView;
Albert Renshaw
la source