Objective-C'de sabit oluşturmanın en iyi yolu nedir


156

Öğrenme amaçları için bir Reddit istemcisi oluşturuyorum. İçinde sabitler olan bir dosyaya ihtiyacım var. Reddit-Prefix.pchSabitleri tüm dosyalar için kullanılabilir hale getirmek için dosyayı dosyaya aktarmayı düşünüyordum . Bir şeyler yapmanın iyi bir yolu mu? Ayrıca, araştırmamı yaptım ve sabitler oluşturmak için birkaç yöntem buldum, ancak hangisini kullanacağımı bilmiyorum:

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

Peki tercih edilen yol hangisidir? Sözleşme nedir? Biliyorum "bağlıdır" ama sorum daha spesifik olarak: Bu çözümlerin her biri için kullanım durumları nelerdir?

Ayrıca, kullanılıyorsa extern constdosyayı içe aktarmam gerekir mi yoksa sabitler dosyayı içe aktarmadan global olarak kullanılabilir mi?

Mantıksal olarak sonuçlandırabileceğim bir enumşey, özel hata etki alanları gibi bir şey tanımlarken en iyi seçimdir (aslında haklı mıyım?). Peki ya diğerleri?


stackoverflow.com/questions/11153156/… lütfen bu bağlantıyı ziyaret edin ... çözümünüz bu
yayında

3
@BhavikKama: Bu, iki özel çözümden farklı olan daha dar bir soru.
Peter Hosey

için - statik const, #define, enum, bu bağlantı yararlıdır stackoverflow.com/questions/1674032/static-const-vs-define-in-c const bu 3 alternatif üzerinde iyi bir açıklama sağlar
Kullanıcı 1.531.343

enumyalnızca integral değerler için kullanışlıdır. #defineve sabitler herhangi bir veri türü olabilir.
rmaddy

const,, static constve extern constkapsam hariç hepsi aynı. Yani gerçekten sadece üç seçenek var.
rmaddy

Yanıtlar:


385

İlk soru sabitlerinizin hangi kapsamda olmasını istediğinizdir, ki bu gerçekten iki sorudur:

  • Bu sabitler tek bir sınıfa özgü mü yoksa uygulamanın her yerinde olması mantıklı mı?
  • Sınıfa özelse, sınıfın istemcileri tarafından mı, yoksa yalnızca sınıf içinde mi kullanılırlar?

Tek bir sınıfa özgü ve dahili iseler, bunları static const.m dosyasının en üstünde olduğu gibi bildirin, şöyle:

static NSString *const MyThingNotificationKey = @"MyThingNotificationKey";

Tek bir sınıfa aitse, ancak diğer sınıflar tarafından herkese açık / kullanılması gerekiyorsa, bunları externbaşlıktaki gibi bildirin ve .m'de tanımlayın:

//.h
extern NSString *const MyThingNotificationKey;

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

Küresel olmaları gerekiyorsa, bunları bir başlıkta beyan edin ve özellikle bu sabitler için karşılık gelen bir modülde tanımlayın.

Bunları, küresel olmalarını istediğiniz farklı düzeylerde farklı sabitler ve basitçe bir araya gelmeyen farklı küresel sabitler için karıştırabilir ve eşleştirebilirsiniz; bunları, her biri kendi başlığına sahip ayrı modüllere koyabilirsiniz. istemek.

Neden olmasın #define ?

Eski cevap “makroların tür bilgisi yok”, ancak bugün derleyiciler değişkenlerin yanı sıra değişmez değerler (makroların genişlediği) için tüm tür denetimi yapma konusunda oldukça zekidirler.

Modern cevap, hata ayıklayıcının makrolarınızı bilmemesi. [myThing addObserver:self forKey:MyThingNotificationKey]Bir hata ayıklayıcı komutunda şunu söyleyemezsiniz :MyThingNotificationKey makro ; hata ayıklayıcı yalnızca değişkense bunu bilebilir.

Neden olmasın enum ?

Rmaddy yorumlarda beni dövdü: enum sadece tamsayı sabitlerini tanımlayabilir. Seri tanımlayıcı numaraları, bit maskeleri, dört baytlık kodlar vb.

Bu amaçlar enumiçin harika ve kesinlikle kullanmalısınız. (Daha da iyisi, kullanımı ve makro .) Diğer şeyler için, gereken başka bir şey kullanmak; tamsayılardan başka bir şey yapmaz.NS_ENUMNS_OPTIONSenum

Ve diğer sorular

Sabitleri tüm dosyalar için kullanılabilir hale getirmek için Reddit-Prefix.pch dosyasındaki dosyayı almayı düşünüyordum. Bir şeyler yapmanın iyi bir yolu mu?

Muhtemelen zararsız, ama muhtemelen aşırı. Sabit başlıklarınızı ihtiyaç duyduğunuz yere aktarın.

Bu çözümlerin her biri için kullanım durumları nelerdir?

  • #define: Oldukça sınırlı. Dürüst olmak gerekirse, bunu sabitler için kullanmak için iyi bir neden olduğundan emin değilim.
  • const: Yerel sabitler için en iyisi. Ayrıca, bunu bir başlıkta bildirdiğiniz ve şimdi tanımladığınız biri için kullanmanız gerekir.
  • static const: Dosyaya özgü (veya sınıfa özgü) sabitler için en iyisi.
  • extern const: Üstbilgideki bir sabiti dışa aktarırken bunu kullanmalısınız.

Ayrıca, kullanılıyorsa extern constdosyayı içe aktarmam gerekir mi yoksa sabitler dosyayı içe aktarmadan global olarak kullanılabilir mi?

Dosyayı, kullandığınız her dosyada veya önek başlığında içe aktarmanız gerekir.


3
Neden kullanmayan static NSString *constiçinde .htamamen dosyanın?
Iulian Onofrei

3
@IulianOnofrei: Bir çerçevede değil, bir uygulamadaysa yapabilirsiniz. Bunu yaparsanız static NSString *const foo = @"foo";, başlığınız dizenin ne olduğunu belirler ve her yerde aynı olmalıdır - dizeyi değiştirirseniz ve farklı taraflar farklı bir dizeyle üstbilginin farklı sürümlerini kullanırsa, dizeler çalışma sırasında eşleşmez zaman. Bir çerçevede, yalnızca sembole erişim sağlamak ve çerçevenin bu sembolün gerçek değerinin tek kaynağı olmasını istiyorsanız, herkes aynı dizeyi tek bir yerden alıyor. Seni externyakalayan şey bu.
Peter Hosey

S hakkında ek not #define: bellekte aynı adrese sahip olmaları garanti edilmez (nasıl bildirildiklerine bağlı olarak, her kullanıldıklarında yeni bir örnek ayırabilirler), bu nedenle kullanmak myObject == MyDefineher zaman beklendiği gibi çalışmaz, ama myObject == MyStaticConstolacak.
Ben Leggiero

static NSString *constBunun yerine yazımda anlam ifade ediyor mu static NSString const*?? Fark var mı ?!
kokos8998

@ kokos8998 bir fark yaratıyor mu? Evet öyle. static NSString const *ile aynıdır static const NSString *ve "sabit bir NSString'e (değiştirilebilir) bir işaretçi" anlamına gelir. Sadece ne istiyorsun static NSString * const- ki bu bir "NSString'in sürekli göstergesidir"
David

8

FOUNDATION_EXPORT

Temelde tanımlandığından ve C, C ++ ve Win32 için uyumlu biçimlerle derlendiğinden FOUNDATION_EXPORTbiraz daha fazla uyumluluk kullanmayı düşünün extern.

NSObjCRuntime.h dosyasında tanımlandığı gibi

#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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.