Apa cara terbaik untuk membuat konstanta di Objective-C

156

Saya membuat klien Reddit untuk tujuan pembelajaran. Saya perlu memiliki file dengan konstanta di dalamnya. Saya berpikir tentang mengimpor file dalam Reddit-Prefix.pchfile untuk membuat konstanta tersedia untuk semua file. Apakah ini cara yang baik untuk melakukan sesuatu? Juga, saya telah melakukan penelitian dan menemukan beberapa metode untuk membuat konstanta, tetapi saya tidak tahu mana yang harus digunakan:

  • #define makro
  • const
  • static const
  • extern const
  • enum

Jadi jalan mana yang lebih disukai? Apa konvensi itu? Saya tahu bahwa "itu tergantung" tetapi pertanyaan saya lebih spesifik adalah: Apa kasus penggunaan untuk masing-masing solusi?

Juga, jika menggunakan extern const, apakah saya perlu mengimpor file, atau konstanta akan tersedia secara global tanpa mengimpor file?

Satu hal yang secara logis dapat saya simpulkan adalah hal itu enum pilihan terbaik ketika mendefinisikan sesuatu seperti domain kesalahan khusus (apakah saya benar-benar benar?). Tapi bagaimana dengan yang lain?

Robert Audi
sumber
stackoverflow.com/questions/11153156/... silakan kunjungi tautan ini ... solusi Anda ada di posting ini
Pengguna 1531343
3
@ BhavikKama: Itu pertanyaan sempit yang membedakan dua solusi spesifik.
Peter Hosey
untuk - static const, #define, enum, tautan ini berguna untuk stackoverflow.com/questions/1674032/static-const-vs-define-in-c yang memberikan penjelasan yang baik tentang 3 alternatif const
Pengguna 1531343
enumhanya berguna untuk nilai integral. #definedan konstanta dapat berupa tipe data apa pun.
rmaddy
const,, static constdan extern constsemuanya sama kecuali untuk ruang lingkup. Jadi sebenarnya hanya ada tiga pilihan.
rmaddy

Jawaban:

385

Pertanyaan pertama adalah ruang lingkup yang Anda inginkan dari konstanta Anda, yang sebenarnya adalah dua pertanyaan:

  • Apakah konstanta ini khusus untuk satu kelas, atau apakah masuk akal untuk menggunakannya di seluruh aplikasi?
  • Jika mereka khusus kelas, apakah mereka untuk digunakan oleh klien dari kelas, atau hanya di dalam kelas?

Jika mereka spesifik dan internal untuk satu kelas, menyatakan mereka sebagai static constdi atas file .m, seperti:

static NSString *const MyThingNotificationKey = @"MyThingNotificationKey";

Jika mereka berkaitan dengan satu kelas tetapi harus publik / digunakan oleh kelas lain, nyatakan mereka sebagai externdi header dan mendefinisikannya di .m:

//.h
extern NSString *const MyThingNotificationKey;

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

Jika harus bersifat global, deklarasikan dalam tajuk dan tentukan dalam modul yang sesuai, khususnya untuk konstanta tersebut.

Anda dapat mencampur dan mencocokkan ini untuk konstanta yang berbeda dengan tingkat yang berbeda tentang bagaimana global yang Anda inginkan, dan untuk konstanta global yang berbeda yang tidak termasuk bersama — Anda dapat menempatkannya dalam modul terpisah, masing-masing dengan header sendiri, jika Anda ingin.

Kenapa tidak #define ?

Jawaban lama adalah "makro tidak memiliki informasi tipe", tetapi kompiler saat ini cukup pintar melakukan semua pengecekan tipe untuk literal (makro yang diperluas) serta variabel.

Jawaban modern adalah karena debugger tidak akan tahu tentang makro Anda. Anda tidak bisa mengatakan [myThing addObserver:self forKey:MyThingNotificationKey]dalam perintah debugger jikaMyThingNotificationKey makro; debugger hanya bisa mengetahuinya jika itu adalah variabel.

Kenapa tidak enum ?

Nah, rmaddy mengalahkan saya dalam komentar: enum hanya dapat mendefinisikan konstanta integer. Hal-hal seperti nomor pengenal serial, bit-mask, kode empat byte, dll.

Untuk keperluan itu, enumsangat bagus dan Anda benar-benar harus menggunakannya. (Bahkan lebih baik, gunakan yang NS_ENUMdan NS_OPTIONSmacro .) Untuk hal-hal lain, Anda harus menggunakan sesuatu yang lain; enumtidak melakukan apa pun kecuali bilangan bulat.

Dan pertanyaan lainnya

Saya berpikir tentang mengimpor file dalam file Reddit-Prefix.pch untuk membuat konstanta tersedia untuk semua file. Apakah ini cara yang baik untuk melakukan sesuatu?

Mungkin tidak berbahaya, tetapi mungkin berlebihan. Impor tajuk konstanta Anda di tempat yang Anda butuhkan.

Apa kasus penggunaan untuk masing-masing solusi tersebut?

  • #define: Cukup terbatas. Sejujurnya saya tidak yakin ada alasan yang baik untuk menggunakan ini untuk konstanta.
  • const: Terbaik untuk konstanta lokal. Selain itu, Anda harus menggunakan ini untuk yang Anda deklarasikan di header dan sekarang mendefinisikan.
  • static const: Terbaik untuk konstanta khusus file (atau khusus kelas).
  • extern const: Anda harus menggunakan ini saat mengekspor konstanta di header.

Juga, jika menggunakan extern const, apakah saya perlu mengimpor file, atau konstanta akan tersedia secara global tanpa mengimpor file?

Anda perlu mengimpor file, baik di setiap file di mana Anda menggunakannya atau di header awalan.

Peter Hosey
sumber
3
Kenapa tidak menggunakan static NSString *constdi .hfile sama sekali?
Iulian Onofrei
3
@IulianOnofrei: Anda bisa, jika ada dalam aplikasi dan bukan framework Jika ya static NSString *const foo = @"foo";, maka tajuk menentukan apa string itu, dan itu harus sama di mana-mana - jika Anda pernah mengubah string dan berbagai pihak menggunakan versi header yang berbeda dengan string yang berbeda, maka string tidak akan cocok saat dijalankan waktu. Dalam suatu kerangka kerja, Anda ingin memberikan akses ke simbol saja, dan membiarkan kerangka kerja menjadi satu-satunya sumber nilai sebenarnya dari simbol itu, sehingga semua orang mendapatkan string yang sama dari satu tempat. Itu yang externmembuatmu.
Peter Hosey
Catatan tambahan pada #defines: mereka tidak dijamin memiliki alamat yang sama dalam memori (tergantung pada bagaimana mereka dinyatakan, mereka dapat mengalokasikan contoh baru setiap kali mereka digunakan), jadi menggunakan myObject == MyDefinetidak akan selalu berfungsi seperti yang diharapkan, tapi myObject == MyStaticConstakan.
Ben Leggiero
Apakah masuk akal dalam mengeja seperti static NSString *constbukannya static NSString const*?? Ada perbedaan ?!
kokos8998
@ kokos8998 apakah ada bedanya? Ya itu. static NSString const *adalah sama dengan static const NSString *dan berarti "a (dapat diubah) pointer ke NSString konstan" - yang agak tidak berguna di sini karena NSString sudah tidak dapat diubah. Apa yang ingin Anda hanya static NSString * const- yang merupakan "pointer konstan ke NSString"
David
8

FOUNDATION_EXPORT

Pertimbangkan FOUNDATION_EXPORTuntuk menggunakan kompatibilitas yang sedikit lebih banyak daripadaextern yang didefinisikan dalam fondasi dan kompilasi ke format yang kompatibel untuk C, C ++, dan Win32.

Seperti yang didefinisikan dalam 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
Steve Moser
sumber