Cuál es la mejor manera de crear constantes en Objective-C


Estoy creando un cliente Reddit con fines de aprendizaje. Necesito un archivo con constantes. Estaba pensando en importar el archivo en el archivo Reddit-Prefix.pch para hacer que las constantes estén disponibles para todos los archivos. ¿Es una buena manera de hacer las cosas? Además, he hecho mi investigación y he encontrado varios métodos para crear constantes, pero no se cual usar:

  • #define macro
  • const
  • static const
  • extern const
  • enum

Entonces, ¿cuál es el camino preferido? ¿Qué es la convención? Sé que "depende" pero mi pregunta más específica es: ¿Cuáles son los casos de uso para cada una de esas soluciones?

Además, si utilizo extern const, ¿necesito importar el archivo, o las constantes estarán disponibles globalmente sin importar el archivo?

Una cosa que podría concluir lógicamente es que enum es el la mejor opción al definir algo como dominios de error personalizados (¿tengo razón?). ¿Pero qué hay de los otros?

Author: Robert Audi, 2013-06-21

2 answers

La primera pregunta es qué alcance quieres que tengan tus constantes, que en realidad son dos preguntas:{[19]]}

  • ¿Son estas constantes específicas de una sola clase, o tiene sentido tenerlas en toda la aplicación?
  • Si son específicos de la clase, ¿son para uso de clientes de la clase, o solo dentro de la clase?

Si son específicos e internos de una sola clase, declararlos como static const en la parte superior de la .archivo m, así:

static NSString *const MyThingNotificationKey = @"MyThingNotificationKey";

Si pertenecen a una sola clase, pero deben ser públicos / utilizados por otras clases, declararlos como extern en el encabezado y definirlos en el .m:

//.h
extern NSString *const MyThingNotificationKey;

//.m
NSString *const MyThingNotificationKey = @"MyThingNotificationKey";

Si deben ser globales, declararlos en un encabezado y definirlos en un módulo correspondiente, específicamente para esas constantes.

Puede mezclar y combinar estas para diferentes constantes con diferentes niveles de cuán globales desea que sean, y para diferentes constantes globales que simplemente no pertenecen juntas,puede ponerlas en módulos separados, cada uno con su propio encabezado, si lo desea.

¿Por qué no #define?

La antigua respuesta es "las macros no tienen información de tipo", pero los compiladores de hoy en día son bastante inteligentes al hacer toda la comprobación de tipos para literales (a qué macros se expanden), así como variables.

La respuesta moderna es porque el depurador no sabrá acerca de sus macros. No se puede decir [myThing addObserver:self forKey:MyThingNotificationKey] en un comando de depurador si MyThingNotificationKey es una macro; el depurador solo puede saberlo si es un variable.

¿Por qué no enum?

Bueno, rmaddy me ganó en los comentarios: enum solo puede definir constantes enteras. Cosas como números de identificación de serie, máscaras de bits, códigos de cuatro bytes, etc.

Para esos propósitos, enum es genial y absolutamente debes usarlo. (Aún mejor, use las macros NS_ENUM y NS_OPTIONS .) Para otras cosas, debe usar otra cosa; enum no hace nada más que números enteros.

Y otras cuestiones

Estaba pensando en importar el archivo con el prefijo Reddit.archivo pch para que las constantes estén disponibles para todos los archivos. Es una buena manera de hacer las cosas?

Probablemente inofensivo, pero probablemente excesivo. Importe sus encabezados de constantes donde los necesite.

¿Cuáles son los casos de uso para cada una de esas soluciones?

  • #define: Bastante limitado. Honestamente no estoy seguro de que haya una buena razón para usar esto para constantes nunca más.
  • const: Mejor para constantes locales. Además, tienes que usar esto para uno que declaraste en un encabezado y ahora estás definiendo.
  • static const: Mejor para constantes específicas del archivo (o específicas de la clase).
  • extern const: Debe usar esto al exportar una constante en un encabezado.

Además, si utilizo extern const, ¿necesito importar el archivo, o las constantes estarán disponibles globalmente sin importar el archivo?

Necesita importar el archivo, ya sea en cada archivo donde lo use o en el encabezado de prefijo.

 372
Author: Peter Hosey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-06-22 09:09:22

FOUNDATION_EXPORT

Considere usar FOUNDATION_EXPORT para un poco más de compatibilidad que extern ya que está definido en foundation y compila a formatos compatibles para C, C++ y Win32.

Como se define en NSObjCRuntime.h

#if defined(__cplusplus)
#define FOUNDATION_EXTERN extern "C"
#else
#define FOUNDATION_EXTERN extern
#endif

#if TARGET_OS_WIN32

    #if defined(NSBUILDINGFOUNDATION)
        #define FOUNDATION_EXPORT FOUNDATION_EXTERN __declspec(dllexport)
    #else
        #define FOUNDATION_EXPORT FOUNDATION_EXTERN __declspec(dllimport)
    #endif

    #define FOUNDATION_IMPORT FOUNDATION_EXTERN __declspec(dllimport)

#else
    #define FOUNDATION_EXPORT  FOUNDATION_EXTERN
    #define FOUNDATION_IMPORT FOUNDATION_EXTERN
#endif
 8
Author: Steve Moser,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-01-14 19:46:38