Qual è il modo migliore per creare costanti in Objective-C


156

Sto creando un client Reddit a fini di apprendimento. Ho bisogno di avere un file con costanti al suo interno. Stavo pensando di importare il file nel Reddit-Prefix.pchfile per rendere le costanti disponibili per tutti i file. È un buon modo di fare le cose? Inoltre, ho fatto la mia ricerca e ho trovato diversi metodi per creare costanti, ma non so quale usare:

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

Quindi in che modo è preferito? Qual è la convenzione? So che "dipende", ma la mia domanda più specifica è: quali sono i casi d'uso per ciascuna di queste soluzioni?

Inoltre, se si utilizza extern const, è necessario importare il file o le costanti saranno disponibili a livello globale senza importare il file?

Una cosa che potrei concludere logicamente è che enumè la scelta migliore quando definisco qualcosa come domini di errore personalizzati (ho davvero ragione?). Ma che dire degli altri?


stackoverflow.com/questions/11153156/… visita questo link ... la tua soluzione è in questo post
Utente 1531343

3
@BhavikKama: Questa è una domanda più ristretta che contrappone due soluzioni specifiche.
Peter Hosey,

per - const statico, #define, enum, questo link è utile stackoverflow.com/questions/1674032/static-const-vs-define-in-c che fornisce una buona spiegazione su quelle 3 alternative di const
Utente 1531343

enumè utile solo per i valori integrali. #definee le costanti possono essere di qualsiasi tipo di dati.
rmaddy,

const, static conste extern constsono tutti uguali ad eccezione dell'ambito. Quindi ci sono davvero solo tre scelte.
rmaddy,

Risposte:


385

La prima domanda è quale ambito desideri avere le tue costanti, che è in realtà due domande:

  • Queste costanti sono specifiche di una singola classe o ha senso averle in tutta l'applicazione?
  • Se sono specifici della classe, devono essere utilizzati dai client della classe o solo all'interno della classe?

Se sono specifici e interni a una singola classe, dichiarali static constall'inizio del file .m, in questo modo:

static NSString *const MyThingNotificationKey = @"MyThingNotificationKey";

Se si riferiscono a una singola classe ma devono essere pubblici / utilizzati da altre classi, dichiararli come externnell'intestazione e definirli in .m:

//.h
extern NSString *const MyThingNotificationKey;

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

Se devono essere globali, dichiarali in un'intestazione e definiscili in un modulo corrispondente, in particolare per quelle costanti.

Puoi mescolarli e abbinarli per diverse costanti con diversi livelli di quanto vuoi che siano globali e per diverse costanti globali che semplicemente non si uniscono - puoi metterle in moduli separati, ognuno con la propria intestazione, se volere.

Perché no #define?

La vecchia risposta è "le macro non hanno informazioni sul tipo", ma i compilatori oggi sono piuttosto intelligenti nel fare tutto il controllo del tipo per i letterali (a cosa si espandono le macro) così come le variabili.

La risposta moderna è perché il debugger non sarà a conoscenza delle tue macro. Non è possibile dire [myThing addObserver:self forKey:MyThingNotificationKey]in un comando debugger se MyThingNotificationKeyè una macro; il debugger può saperlo solo se è una variabile.

Perché no enum?

Bene, rmaddy mi ha battuto nei commenti: enumpuò solo definire costanti intere. Cose come numeri identificativi seriali, maschere di bit, codici a quattro byte, ecc.

Per questi scopi, enumè fantastico e dovresti assolutamente usarlo. (Ancora meglio, usa le macro NS_ENUMeNS_OPTIONS .) Per altre cose, devi usare qualcos'altro; enumnon fa altro che numeri interi.

E altre domande

Stavo pensando di importare il file nel file Reddit-Prefix.pch per rendere le costanti disponibili per tutti i file. È un buon modo di fare le cose?

Probabilmente innocuo, ma probabilmente eccessivo. Importa le intestazioni delle costanti dove ne hai bisogno.

Quali sono i casi d'uso per ciascuna di queste soluzioni?

  • #define: Piuttosto limitato. Onestamente non sono sicuro che ci sia una buona ragione per usarlo più per le costanti.
  • const: Migliore per le costanti locali. Inoltre, devi usarlo per quello che hai dichiarato in un'intestazione e che ora stai definendo.
  • static const: Ideale per costanti specifiche del file (o specifiche della classe).
  • extern const: È necessario utilizzarlo quando si esporta una costante in un'intestazione.

Inoltre, se si utilizza extern const, è necessario importare il file o le costanti saranno disponibili a livello globale senza importare il file?

Devi importare il file, in ogni file in cui lo usi o nell'intestazione del prefisso.


3
Perché non utilizzarlo static NSString *constdel .htutto?
Iulian Onofrei l'

3
@IulianOnofrei: Puoi, se è in un'applicazione e non in un framework. Se lo fai static NSString *const foo = @"foo";, allora l'intestazione determina qual è la stringa e deve essere la stessa ovunque — se mai cambi la stringa e parti diverse usano versioni diverse dell'intestazione con una stringa diversa, le stringhe non corrisponderanno in esecuzione tempo. In un framework, si desidera fornire l'accesso solo al simbolo e lasciare che il framework sia l'unica fonte del vero valore di quel simbolo, in modo che tutti ottengano la stessa stringa da un punto. Questo è ciò che externti prende.
Peter Hosey,

Nota aggiuntiva su #defines: non è garantito che abbiano lo stesso indirizzo in memoria (a seconda di come vengono dichiarati, possono allocare una nuova istanza ogni volta che vengono utilizzati), quindi l'utilizzo myObject == MyDefinenon funzionerà sempre come previsto, ma lo myObject == MyStaticConstfarà.
Ben Leggiero,

Ha senso l'ortografia come static NSString *constinvece di static NSString const*?? Qualche differenza ?!
kokos8998,

@ kokos8998 fa la differenza? Sì lo fa. static NSString const *è lo stesso static const NSString *e significa "un puntatore (modificabile) a una NSString costante" - che qui è un po 'inutile in quanto NSString è già immutabile. Quello che vuoi solo static NSString * const- che è un "puntatore costante a una NSString"
David

8

FOUNDATION_EXPORT

Prendi in considerazione l'utilizzo FOUNDATION_EXPORTper un po 'più di compatibilità rispetto a externquando è definito nella base e viene compilato in formati compatibili per C, C ++ e Win32.

Come definito in 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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.