Utilisation de NSSsortingng statique par rapport aux constantes NSSsortingng en ligne

En Objective-C, je crois comprendre que la directive @ "foo" définit un NSSsortingng constant. Si j'utilise @ "foo" à plusieurs endroits, le même object NSSsortingng immuable est référencé.

Pourquoi est-ce que je vois cet extrait de code si souvent (par exemple dans la réutilisation de UITableViewCell):

static NSSsortingng *CellId = @"CellId"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellId]; if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:style reuseIdentifier:CellId]; 

Au lieu de simplement:

 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"CellId"]; if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:style reuseIdentifier:@"CellId"]; 

Je suppose que c'est pour me protéger de faire une faute de frappe dans le nom de l'identifiant que le compilateur n'attraperait pas. Mais si oui, je ne pourrais pas juste:

 #define kCellId @"CellId" 

et évitez le bit statique NSSsortingng *? Ou est-ce que je manque quelque chose?

C'est une bonne pratique de transformer les littéraux en constantes parce que:

  1. Cela permet d'éviter les fautes de frappe, comme vous l'avez dit
  2. Si vous voulez changer la constante, il vous suffit de la changer en un seul endroit

Je préfère utiliser static const NSSsortingng* static NSSsortingng* const car il est légèrement plus sûr que #define . J'ai tendance à éviter le préprocesseur sauf si j'en ai vraiment besoin.

J'aime toutes les réponses ici sans un simple exemple de la façon de déclarer correctement un … alors …

Si vous voulez que la constante soit visible extérieurement (ie "global") …. déclarez-la comme telle dans un en-tête …

extern NSSsortingng *const MyTypoProneSsortingng;

et définissez-le dans un file .m , en .m toute @implementation comme …

NSSsortingng * const MyTypoProneSsortingng = @"iDoNtKnOwHoW2tYpE";

Cela dit … si vous voulez simplement un static const qui est LOCAL à l'implémentation de votre class ( ou même une certaine méthode! ) … déclarez simplement la string INSIDE l'implémentation (ou la méthode) comme …

static NSSsortingng *MavisBeacon = @"She's a freakin' idiot";

EDIT Bien que je montre comment faire ceci … Je n'ai pas encore été convaincu que ce style est de toute façon meilleur que la déclaration SINGLE ridiculement plus courte, plus simple et less répétitive, à la ..

 #define SomeStupidSsortingng @"DefiningConstantsTwiceIsForIdiots" 

Utilisez #define 's … ils sont beaucoup less ennuyants … Ne laissez pas les pré-processeurs-joueurs-haters vous descendre.

Vous devriez faire la variable statique const .

Une différence entre une variable statique et une macro est que les macros ne fonctionnent pas bien avec les débogueurs. Les macros ne sont pas non plus sécurisées.

La plupart des conseils static-var-vs-macro pour C et C ++ s'appliquent à Obj-C.

Il n'est pas garanti que lors de l'utilisation de @"foo" à plusieurs endroits, le moteur d'exécution utilise le même stockage, et peut ne pas être le cas dans les limites de l'unité de compilation ou de la bibliothèque.
Je préfère utiliser static NSSsortingng *ssortingng = @"foo" , surtout avec beaucoup de strings littérales.

Je suppose que c'est pour me protéger de faire une faute de frappe dans le nom de l'identifiant que le compilateur n'attraperait pas.

Correct. C'est juste une pratique de base en programmation défensive. Le résultat compilé (heureusement) est le même dans les deux cas.

Mais si oui, je ne pourrais pas juste:

 #define kCellId @"CellId" 

et évitez le bit statique NSSsortingng *? Ou est-ce que je manque quelque chose?

Oui. Mais le symbole kCellId serait globalement défini, au less dans votre unité de compilation. La déclaration d'une variable statique rend le symbole local à ce bloc.

Vous verrez généralement les constantes de string définies comme des variables globales ou des variables statiques plutôt que comme des définitions de préprocesseur. Cela permet de garantir que vous ne traitez qu'une seule instance de string entre différentes unités de compilation.

Donc, j'arrive un peu en retard, mais cela a été demandé de nombreuses fois de différentes façons dans les deux zones C / C ++ de SO, mais en gros, voici une version étendue de mon commentaire pour alex grey:

Chaque fois que vous pensez que vous devriez utiliser un #define pour les macros de strings, vous ne devriez probablement pas le faire. La raison en est que les macros #define sont essentiellement des rlocations de regex au préprocesseur. Chaque fois que le préprocesseur voit une macro appelée, il la remplace par ce que vous avez défini. Cela signifie qu'une nouvelle string littérale à chaque fois sera allouée en memory, ce qui est vraiment mauvais dans des endroits comme les identifiants de réutilisation de cellules (ainsi, le code par défaut UITableViewController d'Apple utilise un static).

Utiliser extern / static const pointe à la place toutes les references à une seule place en memory, comme Eonil l'a mentionné. C'est beaucoup plus de memory efficace et performant, ce qui est très important sur les appareils mobiles.