Константы в Objective-C - PullRequest
       67

Константы в Objective-C

993 голосов
/ 12 февраля 2009

Я разрабатываю приложение Какао и использую константы NSString s как способы хранения имен ключей для своих предпочтений.

Я понимаю, что это хорошая идея, потому что она позволяет легко менять ключи при необходимости. Плюс, это целое понятие «отделяй свои данные от своей логики».

В любом случае, есть ли хороший способ сделать эти константы определенными один раз для всего приложения? Я уверен, что есть простой и умный способ, но сейчас мои уроки просто переопределяют те, которые они используют.

Ответы [ 14 ]

1274 голосов
/ 12 февраля 2009

Вы должны создать заголовочный файл как

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

(вы можете использовать extern вместо FOUNDATION_EXPORT, если ваш код не будет использоваться в смешанных средах C / C ++ или на других платформах)

Вы можете включить этот файл в каждый файл, который использует константы, или в предварительно скомпилированный заголовок проекта.

Вы определяете эти константы в файле .m как

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

Constants.m должен быть добавлен к цели вашего приложения / фреймворка, чтобы он был связан с конечным продуктом.

Преимущество использования строковых констант вместо #define d-констант состоит в том, что вы можете проверить равенство, используя сравнение указателей (stringInstance == MyFirstConstant), которое намного быстрее сравнения строк ([stringInstance isEqualToString:MyFirstConstant]) (и легче для чтения IMO).

274 голосов
/ 12 февраля 2009

Самый простой способ:

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

Лучше:

// Prefs.h
extern NSString * const PREFS_MY_CONSTANT;

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

Одним из преимуществ второго является то, что изменение значения константы не вызывает перестройку всей вашей программы.

187 голосов
/ 12 февраля 2009

Есть также одна вещь, чтобы упомянуть. Если вам нужна неглобальная константа, вы должны использовать ключевое слово static.

Пример

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

Из-за ключевого слова static этот констант не виден вне файла.


Незначительная коррекция @ QuinnTaylor : статические переменные видны в блоке компиляции . Обычно это один файл .m (как в этом примере), но он может укусить вас, если вы объявите его в заголовке, который включен в другом месте, так как вы получите ошибки компоновщика после компиляции

118 голосов
/ 18 сентября 2011

В принятом (и правильном) ответе говорится, что «вы можете включить этот файл [Constants.h] ... в предварительно скомпилированный заголовок проекта».

Как новичок, мне было трудно сделать это без дополнительных объяснений - вот как: в вашем файле YourAppNameHere-Prefix.pch (это имя по умолчанию для предварительно скомпилированного заголовка в XCode), импортируйте ваш Constants.h внутри блока #ifdef __OBJC__ .

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

Также обратите внимание, что файлы Constants.h и Constants.m не должны содержать в себе абсолютно ничего, кроме того, что описано в принятом ответе. (Нет интерфейса или реализации).

50 голосов
/ 03 декабря 2011

Я обычно использую способ Барри Уорка и Рахула Гупты.

Хотя мне не нравится повторять одни и те же слова в файлах .h и .m. Обратите внимание, что в следующем примере строка почти идентична в обоих файлах:

// file.h
extern NSString* const MyConst;

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

Поэтому я хотел бы использовать некоторые препроцессорные механизмы С. Позвольте мне объяснить на примере.

У меня есть заголовочный файл, который определяет макрос 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

В моей паре .h / .m, где я хочу определить константу, я делаю следующее:

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

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

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

et вуаля, у меня есть вся информация о константах только в файле .h.

27 голосов
/ 27 января 2013

У меня сам есть заголовок, предназначенный для объявления констант NSStrings, используемых для предпочтений, например:

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

Затем объявляем их в прилагаемом файле .m:

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";

Этот подход хорошо послужил мне.

Изменить: Обратите внимание, что это работает лучше всего, если строки используются в нескольких файлах. Если его использует только один файл, вы можете просто сделать #define kNSStringConstant @"Constant NSString" в файле .m, который использует строку.

25 голосов
/ 03 декабря 2011

Небольшое изменение предложения @Krizz, чтобы оно работало должным образом, если заголовочный файл констант должен быть включен в PCH, что довольно нормально. Так как оригинал импортируется в PCH, он не будет перезагружать его в файл .m, и поэтому вы не получите никаких символов, а компоновщик недоволен.

Однако следующая модификация позволяет ему работать. Это немного запутанно, но это работает.

Вам понадобятся 3 файлы, .h файл с постоянными определениями, файл .h и файл .m, я буду использовать ConstantList.h, Constants.h и Constants.m соответственно. содержимое Constants.h просто:

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

и файл Constants.m выглядит следующим образом:

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

Наконец, файл ConstantList.h содержит фактические объявления, и это все:

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

Несколько замечаний:

  1. Мне пришлось переопределить макрос в файле .m после #undef, используя его для использования макроса.

  2. Мне также пришлось использовать #include вместо #import, чтобы это работало должным образом и чтобы компилятор не видел ранее скомпилированные значения.

  3. Это потребует перекомпиляции вашего PCH (и, вероятно, всего проекта) всякий раз, когда изменяются какие-либо значения, что не имеет место, если они разделены (и дублированы) как обычно.

Надеюсь, это кому-нибудь пригодится.

14 голосов
/ 28 сентября 2011
// Prefs.h
extern NSString * const RAHUL;

// Prefs.m
NSString * const RAHUL = @"rahul";
12 голосов
/ 12 февраля 2009

Как сказал Abizer, вы можете поместить его в файл PCH. Другой способ, который не так грязен, - сделать включаемый файл для всех ваших ключей, а затем либо включить его в файл, в котором вы используете ключи, либо включить его в PCH. Вместе с ними в их собственном файле включения, который, по крайней мере, дает вам одно место для поиска и определения всех этих констант.

11 голосов
/ 12 февраля 2009

Если вы хотите что-то вроде глобальных констант; быстрый грязный способ - поместить объявления констант в файл pch.

...