Ma demande est la suivante. Quand utilise-t-on #import et quand utilise-t-on @class?
Réponse simple: vous #import
ou en #include
cas de dépendance physique. Dans le cas contraire, vous utilisez des déclarations avant ( @class MONClass
, struct MONStruct
, @protocol MONProtocol
).
Voici quelques exemples courants de dépendance physique:
- Toute valeur C ou C ++ (un pointeur ou une référence n'est pas une dépendance physique). Si vous avez un
CGPoint
comme un ivar ou une propriété, le compilateur devra voir la déclaration de CGPoint
.
- Votre superclasse.
- Une méthode que vous utilisez.
Parfois, si j'utilise une déclaration @class, je vois un avertissement de compilateur commun tel que le suivant: "avertissement: le récepteur 'FooController' est une classe directe et @interface correspondante peut ne pas exister."
Le compilateur est en fait très indulgent à cet égard. Il laissera tomber des indices (comme celui ci-dessus), mais vous pouvez facilement supprimer votre pile si vous les ignorez et ne le faites pas #import
correctement. Bien que cela doive (IMO), le compilateur n'applique pas cela. Dans ARC, le compilateur est plus strict car il est responsable du comptage des références. Ce qui se passe, c'est que le compilateur retombe sur une valeur par défaut lorsqu'il rencontre une méthode inconnue que vous appelez. Chaque valeur de retour et paramètre est supposé l'être id
. Ainsi, vous devez supprimer tous les avertissements de vos bases de code car cela doit être considéré comme une dépendance physique. Ceci est analogue à l'appel d'une fonction C qui n'est pas déclarée. Avec C, les paramètres sont supposés être int
.
La raison pour laquelle vous préférez les déclarations avancées est que vous pouvez réduire vos temps de génération par des facteurs car il y a une dépendance minimale. Avec les déclarations avancées, le compilateur voit qu'il y a un nom et peut correctement analyser et compiler le programme sans voir la déclaration de classe ou toutes ses dépendances lorsqu'il n'y a pas de dépendance physique. Les constructions propres prennent moins de temps. Les versions incrémentielles prennent moins de temps. Bien sûr, vous finirez par passer un peu plus de temps à vous assurer que tous les en-têtes dont vous avez besoin sont visibles pour chaque traduction, mais cela se traduit par des temps de construction réduits rapidement (en supposant que votre projet n'est pas minuscule).
Si vous utilisez #import
ou à la #include
place, vous lancez beaucoup plus de travail sur le compilateur que nécessaire. Vous introduisez également des dépendances d'en-tête complexes. Vous pouvez comparer cela à un algorithme de force brute. Lorsque vous #import
, vous glissez des tonnes d'informations inutiles, ce qui nécessite beaucoup de mémoire, d'E / S disque et de CPU pour analyser et compiler les sources.
ObjC est assez proche de l'idéal pour un langage basé sur C en ce qui concerne la dépendance car les NSObject
types ne sont jamais des valeurs - les NSObject
types sont toujours des pointeurs comptés par référence. Ainsi, vous pouvez vous en tirer avec des temps de compilation incroyablement rapides si vous structurez les dépendances de votre programme de manière appropriée et si possible, car il y a très peu de dépendance physique requise. Vous pouvez également déclarer des propriétés dans les extensions de classe pour minimiser davantage la dépendance. C'est un énorme bonus pour les grands systèmes - vous sauriez la différence que cela fait si vous avez déjà développé une grande base de code C ++.
Par conséquent, ma recommandation est d'utiliser les transferts vers l'avant dans la mesure du possible, puis de #import
où il y a une dépendance physique. Si vous voyez l'avertissement ou un autre qui implique une dépendance physique - corrigez-les tous. Le correctif se trouve #import
dans votre fichier d'implémentation.
Au fur et à mesure que vous construisez des bibliothèques, vous classerez probablement certaines interfaces en tant que groupe, auquel cas vous utiliserez #import
cette bibliothèque où la dépendance physique est introduite (par exemple #import <AppKit/AppKit.h>
). Cela peut introduire une dépendance, mais les responsables de la bibliothèque peuvent souvent gérer les dépendances physiques pour vous au besoin - s'ils introduisent une fonctionnalité, ils peuvent minimiser l'impact qu'elle a sur vos builds.