Pertanyaan Konstanta dalam Objective-C


Saya sedang mengembangkan sebuah Biji cokelat aplikasi, dan saya menggunakan konstan NSStringsebagai cara untuk menyimpan nama kunci untuk preferensi saya.

Saya mengerti ini adalah ide yang bagus, karena memungkinkan penggantian kunci yang mudah jika perlu. Selain itu, ini adalah keseluruhan data "terpisah dari logika Anda dari logika".

Anyway, apakah ada cara yang baik untuk membuat konstanta ini didefinisikan sekali untuk seluruh aplikasi? Saya yakin ada cara yang mudah dan cerdas, tetapi saat ini kelas saya hanya mendefinisikan ulang apa yang mereka gunakan.


969
2018-02-11 21:52


asal


Jawaban:


Anda harus membuat file header seperti

// Constants.h
FOUNDATION_EXPORT NSString *const MyFirstConstant;
FOUNDATION_EXPORT NSString *const MySecondConstant;
//etc.

(Kamu dapat memakai extern dari pada FOUNDATION_EXPORT jika kode Anda tidak akan digunakan dalam lingkungan campuran C / C ++ atau pada platform lain)

Anda dapat menyertakan file ini di setiap file yang menggunakan konstanta atau di header yang telah dikompilasi sebelumnya untuk proyek tersebut.

Anda mendefinisikan konstanta ini dalam file .m seperti

// Constants.m
NSString *const MyFirstConstant = @"FirstConstant";
NSString *const MySecondConstant = @"SecondConstant";

Konstanta.m harus ditambahkan ke aplikasi / kerangka sasaran Anda sehingga terhubung ke produk akhir.

Keuntungan menggunakan konstanta string sebagai ganti #defineKonstanta adalah bahwa Anda dapat menguji kesetaraan menggunakan perbandingan pointer (stringInstance == MyFirstConstant) yang jauh lebih cepat daripada perbandingan string ([stringInstance isEqualToString:MyFirstConstant]) (dan lebih mudah dibaca, IMO).


1236
2018-02-11 22:38



Cara termudah:

// Prefs.h
#define PREFS_MY_CONSTANT @"prefs_my_constant"

Cara yang lebih baik:

// Prefs.h
extern NSString * const PREFS_MY_CONSTANT;

// Prefs.m
NSString * const PREFS_MY_CONSTANT = @"prefs_my_constant";

Salah satu manfaat dari yang kedua adalah bahwa mengubah nilai konstanta tidak menyebabkan membangun kembali seluruh program Anda.


264
2018-02-11 22:02



Ada juga satu hal yang perlu disebutkan. Jika Anda membutuhkan konstanta non global, Anda harus menggunakan static kata kunci.

Contoh

// In your *.m file
static NSString * const kNSStringConst = @"const value";

Karena itu static kata kunci, const ini tidak terlihat di luar file.


Koreksi minor oleh @QuinnTaylor: variabel statis terlihat dalam a unit kompilasi. Biasanya, ini adalah file .m tunggal (seperti dalam contoh ini), tetapi dapat menggigit Anda jika Anda mendeklarasikannya di header yang disertakan di tempat lain, karena Anda akan mendapatkan kesalahan tautan setelah kompilasi


182
2018-02-12 16:28



Jawaban yang diterima (dan benar) mengatakan bahwa "Anda dapat menyertakan file [Constants.h] ini ... di header yang telah dikompilasi sebelumnya untuk proyek tersebut."

Sebagai seorang pemula, saya mengalami kesulitan melakukan ini tanpa penjelasan lebih lanjut - begini caranya: Dalam file YourAppNameHere-Prefix.pch Anda (ini adalah nama default untuk header dikompilasi di Xcode), impor Constants.h Anda di dalam #ifdef __OBJC__ blok.

#ifdef __OBJC__
  #import <UIKit/UIKit.h>
  #import <Foundation/Foundation.h>
  #import "Constants.h"
#endif

Juga perhatikan bahwa file-file Constants.h dan Constants.m tidak boleh berisi apa-apa lagi kecuali apa yang dijelaskan dalam jawaban yang diterima. (Tidak ada antarmuka atau implementasi).


117
2017-09-18 14:08



Saya biasanya menggunakan cara diposting oleh Barry Wark dan Rahul Gupta.

Meskipun, saya tidak suka mengulang kata-kata yang sama di file .h dan .m. Perhatikan, bahwa pada contoh berikut garis hampir identik pada kedua file:

// file.h
extern NSString* const MyConst;

//file.m
NSString* const MyConst = @"Lorem ipsum";

Oleh karena itu, apa yang saya suka lakukan adalah menggunakan beberapa mesin C preprocessor. Biar saya jelaskan melalui contoh.

Saya memiliki file header yang mendefinisikan makro STR_CONST(name, value):

// StringConsts.h
#ifdef SYNTHESIZE_CONSTS
# define STR_CONST(name, value) NSString* const name = @ value
#else
# define STR_CONST(name, value) extern NSString* const name
#endif

Dalam pasangan saya .h / .m di mana saya ingin mendefinisikan konstanta yang saya lakukan berikut ini:

// myfile.h
#import <StringConsts.h>

STR_CONST(MyConst, "Lorem Ipsum");
STR_CONST(MyOtherConst, "Hello world");

// myfile.m
#define SYNTHESIZE_CONSTS
#import "myfile.h"

et voila, saya memiliki semua informasi tentang konstanta dalam .h file saja.


50
2017-12-02 21:53



Sedikit modifikasi saran dari @Krizz, agar berfungsi dengan baik jika file header konstanta dimasukkan ke dalam PCH, yang agak normal. Karena aslinya diimpor ke PCH, ia tidak akan memuatnya kembali ke dalam .m file dan dengan demikian Anda tidak mendapatkan simbol dan linker tidak senang.

Namun, modifikasi berikut memungkinkannya untuk bekerja. Ini agak berbelit-belit, tetapi itu berhasil.

Kamu akan membutuhkan 3 file, .h file yang memiliki definisi konstan, .h file dan .m file, saya akan menggunakan ConstantList.h, Constants.h dan Constants.m, masing-masing. isi dari Constants.h hanya:

// Constants.h
#define STR_CONST(name, value) extern NSString* const name
#include "ConstantList.h"

dan Constants.m file seperti:

// Constants.m
#ifdef STR_CONST
    #undef STR_CONST
#endif
#define STR_CONST(name, value) NSString* const name = @ value
#include "ConstantList.h"

Akhirnya, itu ConstantList.h file memiliki deklarasi aktual di dalamnya dan itu semua:

// ConstantList.h
STR_CONST(kMyConstant, "Value");
…

Beberapa hal yang perlu diperhatikan:

  1. Saya harus mendefinisikan kembali makro dalam .m mengajukan setelah  #undefing untuk makro yang akan digunakan.

  2. Saya juga harus menggunakannya #include dari pada #import agar ini berfungsi dengan baik dan hindari compiler melihat nilai yang dikompilasi sebelumnya.

  3. Ini akan memerlukan rekompilasi PCH Anda (dan mungkin seluruh proyek) kapan pun nilai apa pun diubah, yang tidak terjadi jika mereka dipisahkan (dan diduplikasi) seperti biasa.

Semoga bermanfaat bagi seseorang.


25
2017-12-03 00:03



Saya sendiri memiliki header yang didedikasikan untuk mendeklarasikan NSString konstan yang digunakan untuk preferensi seperti:

extern NSString * const PPRememberMusicList;
extern NSString * const PPLoadMusicAtListLoad;
extern NSString * const PPAfterPlayingMusic;
extern NSString * const PPGotoStartupAfterPlaying;

Kemudian deklarasikan dalam file .m yang disertakan:

NSString * const PPRememberMusicList = @"Remember Music List";
NSString * const PPLoadMusicAtListLoad = @"Load music when loading list";
NSString * const PPAfterPlayingMusic = @"After playing music";
NSString * const PPGotoStartupAfterPlaying = @"Go to startup pos. after playing";

Pendekatan ini telah membantu saya dengan baik.

Edit: Perhatikan bahwa ini berfungsi paling baik jika string digunakan dalam banyak file. Jika hanya satu file yang menggunakannya, Anda bisa melakukannya #define kNSStringConstant @"Constant NSString" dalam file .m yang menggunakan string.


24
2018-01-26 23:15



// Prefs.h
extern NSString * const RAHUL;

// Prefs.m
NSString * const RAHUL = @"rahul";

14
2017-09-28 04:37



Seperti kata Abizer, Anda bisa memasukkannya ke dalam file PCH. Cara lain yang tidak begitu kotor adalah membuat file include untuk semua kunci Anda dan kemudian memasukkannya ke dalam file yang Anda gunakan kunci, atau, masukkan ke dalam PCH. Dengan mereka di file include mereka sendiri, setidaknya memberi Anda satu tempat untuk mencari dan mendefinisikan semua konstanta ini.


12
2018-02-11 22:05



Jika Anda menginginkan sesuatu seperti konstanta global; cara cepat kotor adalah menempatkan deklarasi konstan ke dalam pch mengajukan.


11
2018-02-11 21:56