В Objective C мое понимание - то, что директива "нечто" определяет постоянный NSString. Если я использую "нечто" в нескольких местах, на тот же неизменный объект NSString ссылаются.
Почему делают я вижу этот фрагмент кода так часто (например, в повторном использовании UITableViewCell):
static NSString *CellId = @"CellId";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellId];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:style reuseIdentifier:CellId];
Вместо просто:
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"CellId"];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:style reuseIdentifier:@"CellId"];
Я предполагаю, что это должно защитить меня от создания опечатки на имя идентификатора, которое не поймал бы компилятор. Но Если так, не мог я просто:
#define kCellId @"CellId"
и избегайте статического NSString * бит? Или я пропускаю что-то?
Хорошая практика - превращать буквы в константы, потому что:
Я предпочитаю использовать статический const NSString*
статический NSString* const
, потому что это немного безопаснее, чем #define
. Я стараюсь избегать препроцессора, если он мне действительно не нужен
Вы должны сделать статическую переменную const
.
Одно различие между статической переменной и макросом заключается в том, что макросы плохо работают с отладчиками. Макросы также небезопасны по типу.
Большая часть рекомендаций static-var-vs-macro для C и C ++ применима к Obj-C.
Я предполагаю, что это должно защитить меня от опечатки в имени идентификатора, которую компилятор не обнаружит.
Верно. Это просто базовая практика защитного программирования. Скомпилированный результат (надеюсь) в любом случае будет таким же.
Но если так, не мог бы я просто:
#define kCellId @ "CellId"
и избежать статического бита NSString *? Или я что-то упустил?
Да. Но символ kCellId
будет определяться глобально, по крайней мере, в вашем модуле компиляции. Объявление статической переменной делает символ локальным для этого блока.
Обычно строковые константы определены как глобальные или статические переменные, а не как определения препроцессора. Это помогает гарантировать, что вы имеете дело только с одним экземпляром строки между разными модулями компиляции.
Не гарантируется, что при использовании @"foo"
в нескольких местах для них используется одно и то же хранилище, и уж точно не гарантируется, что это происходит за пределами модуля компиляции или библиотеки.
.
Я бы предпочел использовать статический NSString *string = @"foo"
, особенно с большим количеством литературных строк.