Problème de références croisées sur delegates
muqaddar
Administrateur
Depuis quelques temps, j'ai quelques soucis de compilation suite à des imports de classes qui contiennent des délégués. A vrai dire, je ne sais pas si c'est un problème logique... ou si c'est Xcode 4.0 qui a un soucis.
Fichier VinocellaViewController.h
Fichier CountriesViewController.h
Et, à partir du moment où j'importe ce fameux CountriesViewController.h dans VinocellaViewController.h, je me tape ce genre d'erreurs (cf capture) En gros, beaucoup de classe qui importent VinocellaViewController.h pètent un plomb... et ne trouvent plus le SearchDataSource qui est bien importé dans ces classes.
Sauf que pour implémenter mon mécanisme de delegate lié à CountriesViewController, je suis obligé d'importer le .h n'est-ce pas ?
Car @class CountriesViewController; ne permet pas de faire reconnaà®tre le protocole créé dans CountriesViewController...
Fichier VinocellaViewController.h
#import "CountriesViewController.h"<br /><br />@protocol SearchDataSource<br /><br />- (NSUInteger)countryId;<br />- (void)setCountryId:(NSUInteger)aCountryId;<br /><br />@end<br /><br />@interface VinocellaViewController : UIViewController <SearchDataSource, CountriesViewControllerDelegate><br />{<br />}<br />@end
Fichier CountriesViewController.h
#import "ReferenceViewController.h"<br />#import "VinocellaViewController.h"<br /><br />@protocol CountriesViewControllerDelegate<br />@optional<br />- (void)dismissCurrentPopover:(UIPopoverController*)aPopoverController;<br />@end<br /><br />@interface CountriesViewController : UIViewController<br />{<br /> id<ReferenceDataSource> referenceDataSource;<br /> id<SearchDataSource> searchDataSource;<br /> <br /> id<CountriesViewControllerDelegate> delegate;<br /> UIPopoverController *popoverController;<br />}
Et, à partir du moment où j'importe ce fameux CountriesViewController.h dans VinocellaViewController.h, je me tape ce genre d'erreurs (cf capture) En gros, beaucoup de classe qui importent VinocellaViewController.h pètent un plomb... et ne trouvent plus le SearchDataSource qui est bien importé dans ces classes.
Sauf que pour implémenter mon mécanisme de delegate lié à CountriesViewController, je suis obligé d'importer le .h n'est-ce pas ?
Car @class CountriesViewController; ne permet pas de faire reconnaà®tre le protocole créé dans CountriesViewController...
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Donc dans VinocellaViewController.h:
Oh purée !
Je l'avais jamais vu auparavant ou n'y avais pas fait attention !
Merci zoc.
De la classe ?
Du protocole tu veux dire non ? Tu m'as un peu perdu là .
Sinon tu fais un DataSourceProtocol.h dans lequel tu mets juste ton @protocol, et tu #import "DataSourceProtocol.h" à la fois dans ton "VinocellaViewController.h", mais aussi dans ton "CountriesViewController.h" (dans lequel tu n'aurais plus à faire #import "VinocellaViewController.h" du coup).
Parce que là ça m'a l'air un peu fouilli de déclarer un @protocol dans le même fichier qu'une autre classe alors que ce protocol n'est pas utilisé QUE par cette classe. Autant pour le "CountriesViewControllerDelegate" ça se justifie tout à fait de le mettre dans le même fichier que la classe CountriesViewController elle-même, autant pour ton SearchDataSource qui est utilisé à divers endroit je suis pas sûr que ça soit pas plus clair et propre de le mettre à part, surtout si dans l'autre fichier "CountriesViewController.h" tu ne fais le #import "VinocellaViewController.h"... QUE pour importer ce SearchDataSource sans avoir besoin de la classe VinocellaViewController à cet endroit.
Effectivement, je ne l'ai jamais fait (mettre un protocole dans un fichier à part), et j'avoue que ça éclaircirait encore le code, sa compréhension, et la compréhension des imports !
Merci ! (super content de structurer de plus en plus mon code sur des applis conséquentes)
Et comme je suis fainéant, je me contente de les appeler DataSource et de ne faire qu'un protocole au lieu de 2 pour ne pas avoir ensuite à en importer 2 dans les classes qui en ont besoin...
Bien que tout a l'air de marcher, je me tape des warnings étranges.
Les forward declarations c'est bien, mais faut quand même qu'il ait les définitions à un moment donné, surtout dans l'implémentation, pour vérifier que tu as bien implémenté toutes les méthodes @required du protocole, etc !
Je sèche depuis quelques heures (et je répète que tout marche pourtant), mais je déteste les warnings...
cf capture.
Pour le coup, je vais finir par me demander si c'est pas Xcode 4 qui a un plomb dans l'aile.
(je précise à nouveau que tout tourne comme une horloge dans l'app)
Tu lui indiques que ta classe implémente le protocole A (en la mettant dans les chevrons <...>), mais quand il voit ça lui il a besoin de savoir en détail à quoi correspond ce @protocol, plus que son nom mais bien quelles sont les méthodes que ta classe va devoir implémenter pour se rendre conforme à ce protocole.
Or ça tu ne lui as mis nulle part, puisque tu n'as indiqué que la (forward-)déclaration de ton @protocol, mais pas sa définition (avec sa liste de méthodes) !
Donc il fait que j'importe le .h où se trouvent les listes de méthodes ? (du coup je reviens un peu au problème du début de mon sujet, bien que je ne l'ai plus puisque j'ai créé des fichiers à part pour mes 2 principaux protocoles)
A mon avis c'est la (seule) solution à ton problème vu que tes protocoles sont un peu génériques (et pas fortement liés à la classe comme ça peut être le cas pour un UITableView et son UITableViewDataSource ou UITableViewDelegate, dans ton cas tu utilises ton protocol pour d'autres classes aussi c'est là toute la différence) et utilisés par diverses classes, il faut cloisonner.