ios objective-c nsstring

ios - uso estático de NSString vs. constantes de NSString en línea



objective-c (6)

En Objective-C, entiendo que la directiva @ "foo" define una constante NSString. Si utilizo @ "foo" en varios lugares, se hace referencia al mismo objeto NSString inmutable.

¿Por qué veo este fragmento de código tan a menudo (por ejemplo, en la reutilización de UITableViewCell)?

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

En lugar de simplemente

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

Supongo que es para protegerme de crear un error tipográfico en el nombre del identificador que el compilador no captaría. Pero si es así, ¿no podría simplemente:

#define kCellId @"CellId"

y evitar el bit NSString * estático? ¿O me estoy perdiendo algo?


Supongo que es para protegerme de crear un error tipográfico en el nombre del identificador que el compilador no captaría.

Correcto. Es solo práctica básica de programación defensiva. El resultado compilado (con suerte) es el mismo de cualquier manera.

Pero si es así, ¿no podría simplemente:

#define kCellId @"CellId"

y evitar el bit NSString * estático? ¿O me estoy perdiendo algo?

Sí. Pero el símbolo kCellId se definiría globalmente, al menos en su unidad de compilación. La declaración de una variable estática hace que el símbolo sea local para ese bloque.

Por lo general, verá constantes de cadena definidas como variables globales o variables estáticas en lugar de definido por el preprocesador. Esto ayuda a garantizar que solo se trata de una única instancia de cadena entre diferentes unidades de compilación.


Debes hacer que la variable estática const .

Una diferencia entre la variable estática y una macro es que las macros no funcionan bien con los depuradores. Las macros tampoco son tipo seguras.

Gran parte del asesoramiento static-var-vs-macro para C y C++ aplica a Obj-C.


Es una buena práctica convertir los literales en constantes porque:

  1. Ayuda a evitar errores tipográficos, como dijiste
  2. Si quieres cambiar la constante, solo tienes que cambiarla en un solo lugar

Prefiero usar static const NSString* static NSString* const porque es un poco más seguro que #define . Tiendo a evitar el preprocesador a menos que realmente lo necesite.


Me encantan todas las respuestas aquí sin un simple ejemplo de cómo declarar correctamente una ... así que ...

Si desea que la constante sea externamente visible (es decir, "global") ... declare como tal en un encabezado ...

extern NSString *const MyTypoProneString;

y defínalo en un archivo .m , FUERA cualquier @implementation como ...

NSString * const MyTypoProneString = @"iDoNtKnOwHoW2tYpE";

Dicho eso ... si simplemente quieres una static const que ES LOCAL para la implementación de tu clase (¡ o incluso un método determinado! ) ... simplemente declara la cadena DENTRO de la implementación (o método) como ...

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

EDITAR Aunque sí muestro cómo hacerlo ... aún no me he convencido de que este estilo sea de ninguna manera mejor que la declaración SINGLE, ridículamente más corta, más simple y menos repetitiva.

#define SomeStupidString @"DefiningConstantsTwiceIsForIdiots"

Usa #define ... son mucho menos molestos ... Solo que no dejes que los enemigos preprocesadores-jugadores te depriman.


No se garantiza que al usar @"foo" en múltiples lugares, el tiempo de ejecución use el mismo almacenamiento para ellos, y ciertamente no puede ser el caso a través de la unidad de compilación o los límites de la biblioteca.
Preferiría usar static NSString *string = @"foo" , especialmente con muchas cadenas literales.


Por lo tanto, estoy entrando en esto un poco tarde, pero esto se ha preguntado en numerosas ocasiones de varias maneras en las dos áreas C / C ++ de SO, pero básicamente aquí hay una versión ampliada de mi comentario a alex gray:

Cada vez que piense que debería usar un #define para macros de cadena, lo más probable es que no lo haga. La razón es porque las macros #define son básicamente reemplazos de expresiones regulares para el preprocesador. Cada vez que el preprocesador ve una macro llamada, la reemplaza con lo que sea que haya definido. Esto significa que un nuevo literal de cadena cada vez se asignará a la memoria, lo cual es realmente malo en lugares como los identificadores de reutilización de celdas (por lo que el código por defecto de UITableViewController de Apple usa una estática).

Usar const externo / estático apunta todas las referencias a un solo lugar en la memoria, como lo mencionó Eonil. Esto es mucho más eficiente y eficiente en la memoria, lo cual es muy importante en los dispositivos móviles.