Подтвердить что ты не робот

Когда использовать статическую строку vs. #define

Я немного смущен, когда лучше всего использовать:

static NSString *AppQuitGracefullyKey = @"AppQuitGracefully";

вместо

#define AppQuitGracefullyKey    @"AppQuitGracefully"

Я видел такие вопросы, как это для C или С++, и я думаю, что здесь различно то, что это специально для Objective C, используя объект, а на устройстве, таком как iPhone, может быть стек, кодовое пространство или которые я еще не понимаю.

Одно использование:

appQuitGracefully =  [[NSUserDefaults standardUserDefaults] integerForKey: AppQuitGracefullyKey];

Или это просто вопрос стиля?

Спасибо.

4b9b3361

Ответ 1

Если вы используете статический код, компилятор будет вставлять ровно одну копию строки в ваши двоичные и простые указатели на эту строку, что приведет к созданию более компактных двоичных файлов. Если вы используете #define, при каждом использовании будет существовать отдельная копия строки, хранящейся в источнике. Постоянная коалесценция будет обрабатывать многие из дублирующих устройств, но вы делаете компоновщик работать без усилий.

Ответ 2

См. "static const" vs "# define" vs "перечисление" . Основным преимуществом static является безопасность типов.

Кроме того, подход #define представляет гибкость встроенной конкатенации строк, которая не может быть выполнена со статическими переменными, например.

#define ROOT_PATH @"/System/Library/Frameworks"
[[NSBundle bundleWithPath:[email protected]"/UIKit.framework"] load];

но это, вероятно, не очень хороший стиль:).

Ответ 3

После некоторого поиска (этого вопроса/ответа, среди прочего), я думаю, важно сказать, что в любое время, когда вы используете строковый литерал @"AppQuitGracefully" константа string и независимо от того, сколько раз вы его используете, он укажет на тот же объект.

Итак, я думаю (и извиняюсь, если ошибаюсь), что это предложение в правильном ответе неверно: If you use a #define, there will be a separate copy of the string stored in the source on each use.

Ответ 4

Я бы не рекомендовал ни того, что вы должны использовать extern. Objective-c уже определяет FOUNDATION_EXPORT, который более портативный, чем extern, поэтому глобальный экземпляр NSString будет выглядеть примерно так:

.h

FOUNDATION_EXPORT NSString * const AppQuitGracefullyKey;

.m

NSString * const AppQuitGracefullyKey = @"AppQuitGracefully";

Я обычно помещаю их в файлы декларации (например, MyProjectDecl.h) и импортирует, когда мне нужно.

Есть несколько отличий от этих подходов:

  • #define имеет несколько недостатков, например, не безопасный тип. Верно, что для этого есть обходные пути (например, #define ((int)1)), но что это за точка? И кроме того, есть отладочные недостатки этого подхода. Компиляторы предпочитают константы. См. это обсуждение.
  • статические глобальные переменные видны в объявленном файле.
  • extern делает переменную видимой для всех файлов. Это контрастирует со статикой.

Статические и внешние отличаются видимостью. Также примечательно, что ни один из этих подходов не дублирует строку (даже не #define), поскольку компилятор использует String Interning, чтобы предотвратить это. В этот пост NSHipster они показывают доказательство:

NSString *a = @"Hello";
NSString *b = @"Hello";
BOOL wtf = (a == b); // YES

Оператор == возвращает YES только в том случае, если две переменные указывают на один и тот же экземпляр. И, как вы можете видеть, это так.

Вывод: используйте FOUNDATION_EXPORT для глобальных констант. Он отлаживает дружеские отношения и будет виден всем вашим проектом.

Ответ 5

Я использую static, когда мне нужно экспортировать символы NSString из библиотеки или рамки. Я использую #define, когда мне нужна строка во многих местах, которые я могу легко изменить. Во всяком случае, компилятор и компоновщик позаботятся об оптимизации.

Ответ 6

ИСПОЛЬЗОВАНИЕ #define:

вы не можете отлаживать значение идентификатора

Работа С#define и другими макросами - это задание Pre-Processor, Когда вы сначала нажмете Build/Run, он будет обрабатывать исходный код, он будет работать со всеми макросами (начиная с символа #),

Предположим, вы создали,

#define LanguageTypeEnglish @"en"

и использовал это в двух местах в вашем коде.

NSString *language = LanguageTypeEnglish;
NSString *languageCode = LanguageTypeEnglish;

он заменит "LanguageTypeEnglish" на @"en" во всех местах. Таким образом, будут созданы 2 копии @"en". iee

NSString *language = @"en";
NSString *languageCode = @"en";

Помните, что до этого процесса компилятор не находится на картинке.

После предварительной обработки всех макросов, компилятор входит в изображение, и он получит код ввода, подобный этому,

NSString *language = @"en";
NSString *languageCode = @"en";

и скомпилируйте его.

ИСПОЛЬЗОВАНИЕ static:

он уважает область действия и безопасен по типу. вы можете отлаживать значение идентификатора

В процессе компиляции, если найден компилятор,

static NSString *LanguageTypeRussian = @"ru";

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

Таким образом, используя static, в пределах области создается только одна копия переменной.