2010-08-18 3 views
1

Je reçois cet avertissement. Ce que j'essaie de faire, c'est d'avoir une famille de classes et une famille parallèle de protocoles. La pièce de classe a une déclaration comme celle-ci:Objective-C: Le type "warning: property 'owner" ne correspond pas au type de propriété' PieceModel 'du protocole "

@interface Piece : NSManagedObject <PieceModel> 
{ 
} 

... 

@property (nonatomic, retain) Player *owner; 

... 

@end 

PieceModel a cette

@protocol PieceModel <NSObject> 

... 

@property (readonly, nonatomic, retain) id <PlayerModel> owner; 

@end 

Et bien sûr:

@interface Player : NSManagedObject <PlayerModel> { ... 

Il me semble que cela devrait tous être totalement sûr. Les utilisateurs des protocoles voient que quelque chose conforme au protocole PieceModel a un propriétaire qui doit se conformer au protocole PlayerModel. En fait, chaque instance de la classe Piece retourne une instance Player pour la propriété owner, qui est conforme au protocole PlayerModel. Je vois pourquoi il y a un tel avertissement. Il ne serait pas aussi sûr d'essayer d'assigner un objet conforme à PlayerModel au propriétaire, car il pourrait ne pas appartenir à la classe Player, mais ce n'est pas un problème dans ce cas car la propriété est déclarée en lecture seule pour le protocole. Notez que j'ai également déclaré la propriété en tant que conserver, ce qui si je ne me trompe est sans signification pour une propriété readonly, mais j'ai également reçu un avertissement différent sur une incompatibilité entre le protocole et la classe si je ne le faisais pas. Au moins, le compilateur ne se plaint pas qu'une propriété est en lecture seule et l'autre ne l'est pas.

Je sais que je pourrais simplement déclarer la propriété de classe comme renvoyant id <PlayerModel>, mais ce serait indésirable pour plusieurs raisons. Les utilisateurs d'objets Piece qui les ont statiquement typés comme Pieces devraient faire un cast pour obtenir quelque chose de typé statiquement en tant que joueur. Aussi, je devrais écrire l'implémentation de la propriété moi-même au lieu de simplement utiliser @synthesize, ou dans ce cas en fait @dynamic; Les données de base génèrent les implémentations de propriété. Donc, puis-je demander au compilateur de supprimer cet avertissement? Ou existe-t-il un meilleur moyen d'écrire ce code qui ne génèrera pas l'avertissement?

Répondre

0

Cela génère pas d'avertissement ...

@protocol PlayerModel <NSObject> 
@end 

@protocol PieceModel <NSObject> 
- (id<PlayerModel>)owner; 
@end 

@interface Player : NSObject <PlayerModel> { 
} 
@end 

@interface Piece : NSObject <PieceModel> { 
} 
@property (nonatomic,retain) Player* owner; 
@end 

Vous ne serez pas alors bien sûr capable d'utiliser @synthesize pour PieceModel.owner, mais ce n'est pas tellement de travail supplémentaire. Rappelez-vous que les déclarations @property sont essentiellement des raccourcis pour déclarer le setter et getter et définir le comportement des méthodes générées par @synthesize. Gardez aussi à l'esprit que la notation par points pour accéder aux propriétés n'est que du sucre syntaxique, donc si vous aimez la notation par points, vous pourrez toujours l'utiliser pour accéder à 'owner' sur les variables déclarées <PieceModel>.

+0

Nope, puis je reçois: avertissement: class 'Piece' ne pas mettre pleinement en œuvre le protocole 'PieceModel' avertissement: définition de la méthode pour '-owner' not found avertissement: 'Piece' mise en œuvre incomplète de classe '- (id ) owner;' est identique à '@property (readonly) id owner;', mais le compilateur ne semble pas assez intelligent pour le comprendre dans le cas d'une classe conforme à un protocole . Même si je déclare PieceModel comme: @protocol PieceModel - (Player *) propriétaire; @end que je ne veux pas faire, je reçois les mêmes avertissements. – Greg

+0

Hmm, j'ai essayé quelque chose d'autre et il semble que votre solution fonctionne mais pas avec la définition @dynamic de la propriété. – Greg

+0

Correct. Ma suggestion évite spécifiquement de déclarer @property dans le protocole PieceModel. – imaginaryboy

0

Le propriétaire a-t-il une relation dans votre modèle de données? Si c'est le cas, vous pourriez trouver que le compilateur est confus car NSManagedObject doit y répondre.

Sinon, cela ressemble à une limitation de la façon dont les propriétés sont gérées dans les sous-classes ou les implémentations de protocoles. Si vous remplacez NSManagedObject par NSObject dans Piece and Player et que vous rencontrez toujours le problème, il peut être utile de rapporter un bogue à Apple. Pour contourner le problème, je pense que vous ne devriez pas déclarer la propriété dans Piece et déclarer un setter séparé pour le propriétaire, c'est-à-dire i.e.

@interface Piece : NSManagedObject <PieceModel> 
{ 
} 
... 

//@property (readonly, nonatomic, retain) id<PlayerModel> owner; 
// property declaration not needed because it's in the protocol 

-(void) setOwner: (Player*) newOwner; 
... 

@end 

et de mettre en œuvre le setter manuellement. Sur une note non liée, je ne dirais pas que les propriétés sont non atomiques à moins d'avoir des preuves de la part d'un profileur que cela fournit une amélioration significative des performances.

+0

Oui, le propriétaire est une relation dans le modèle de données. Il semble que cela pourrait faire partie du problème. La suggestion imaginaryboy se débarrasse des avertissements liés à ce problème si je fournis une mise en œuvre des accesseurs comme celui-ci: - (joueur *) propriétaire { ...} - (void) SetOwner: (Joueur *) owner { ... } Cela ne fonctionne pas si j'utilise le mot clé @dynamic pour indiquer que les données de base fournissent les accesseurs. Le compilateur n'est pas conscient que l'accesseur approprié existera. Mais est-ce que @dynamic n'est pas censé informer le compilateur que la classe répondra aux sélecteurs exactement comme ci-dessus? – Greg

+0

J'ai essayé votre suggestion et elle se débarrasse des avertissements, mais il y a quelques inconvénients. Tout d'abord, en théorie, le code qui a un objet Piece statiquement typé peut vouloir accéder au propriétaire en tant que joueur, pas en tant que PlayerModel, sans un cast. Deuxièmement, il y a la partie sur l'écriture du setter moi-même, ce que je pourrais faire, mais je préfère ne pas pour cela et plusieurs autres classes avec lesquelles j'ai un problème similaire. Cela fonctionne comme est; J'essaie juste de me débarrasser des douzaines d'avertissements que je reçois. Ces fausses alertes me permettent de ne pas remarquer les avertissements importants. – Greg

+1

Eh bien, je suis désolé, mais vous semblez demander la langue pour faire des choses qu'il ne peut pas. Franchement, je pense que votre idée de refléter votre modèle de données avec des protocoles est erronée. Chaque fois que vous modifiez votre modèle de données, vous devez modifier manuellement les protocoles affectés ainsi que vos objets gérés personnalisés. Cela ressemble à un cauchemar de maintenance. – JeremyP

Questions connexes