У меня есть чтение в нескольких сообщениях и в инструкциях по коду Apple, которые в Строковых константах Objective C должны быть определены как экстерн NSString *const MY_CONSTANT;
и что #define директивы нужно избежать. Почему это? Я знаю это #define
выполняется во время перед компиляцией, но вся строка совместно использует тот же адрес памяти. Единственное преимущество, которое я считал, состояло в том, что, если константа должна быть обновлена или изменилась, Вы не должны перекомпилировать свой весь проект. Так, чтобы я s причина, почему #define нужно избежать?
Спасибо
ОБНОВЛЕНИЕ: В этом случае хорошо для использования #define или существует лучший подход?
/* Constants Definition */
#define SERVER_URL @"http://subdomain.domain.edu.ar/Folder/"
NSString *const ServerURL = SERVER_URL;
NSString *const LoginURL = SERVER_URL@"welcome.asp";
NSString *const CommandURL = SERVER_URL@"com.asp";
Практическая причина использования константы в отличие от определения заключается в том, что вы можете делать прямые сравнения (используя ==) вместо использования isEqual:
. Рассмотрим:
NSString * const kSomeStringConstant = @"LongStringConstantIsLong";
...
[someArray addObject:kSomeStringConstant];
if ([someArray lastObject] == kSomeStringConstant)
{
...
}
Это сработает, так как сравнение ==
будет сравнивать идентичные константные указатели с одним объектом NSString
. Однако, используя #define
:
#define STRING_CONSTANT @"MacrosCanBeEvil";
...
[SomeArray addObject:STRING_CONSTANT]; // a new const `NSString` is created
if ([someArray lastObject] == STRING_CONSTANT) // and another one, here.
{
...
}
Это не сработало бы -, так как эти две строки будут иметь уникальные указатели. Для того, чтобы эффективно сравнить их, вам пришлось бы делать посимвольное сравнение, используя isEqual:
if ([[someArray lastObject] isEqual:STRING_CONSTANT])
{
...
}
Это может быть гораздо более дорогостоящим с точки зрения времени исполнения, чем простое ==
сравнение.
Другой мотив может быть размер самого исполняемого файла. На самом деле #определенная константа появлялась бы на месте, где бы она ни использовалась в коде. Это может означать, что строка появляется много раз в вашем исполняемом файле. Напротив, константа должна (в современных компиляторах) быть определена только один раз, и все дальнейшие использования ссылались бы на указатель на это одно определение.
Теперь, прежде чем кто-то наорет на меня за преждевременную оптимизацию, считайте, что эти два подхода практически идентичны с точки зрения реализации, но метод константы намного превосходит по размеру кода и времени исполнения.
.Не гарантируется, что в целом приложении будет только один объект NXConstantString для заданного строкового литерала. Вполне вероятно, что разные модули компиляции могут иметь разные объекты для одной и той же константной строки. Например, если кто-то напишет плагин, то одна константная строка будет сгенерирована для вхождений этого NSString литерала в плагине, а другая - для вхождений в хост-приложение, и это не будет указатель-эквивалент.
. Лучший аргумент, который я слышал, это то, что строки const
появляются в отладчике, а макросы нет.
Насколько я знаю, #define
позволяет определить только строковые константы в стиле C. Чтобы создать объект константы NSString, необходимо объявить его в заголовке, а затем дать ему значение в одном из .m файлов.
Заголовочный файл:
extern NSString *MyConstantString;
Main file:
NSString *MyConstantString = @"String value";