Использование #define в операторе if

Можно ли использовать #define в утверждении "если"? Следующий код работает, но я получаю предупреждение о том, что макрос переопределяется.

if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
 #define TableViewHeight 916
 #define DisplayHeight 1024
 #define DisplayWidth 768
}
else {
 #define TableViewHeight 374
 #define DisplayHeight 480
 #define DisplayWidth 320
}

Я тоже попробовал это, но это не сработало:

#ifdef UIUserInterfaceIdiomPad
 #define TableViewHeight 916
 #define DisplayHeight 1024
 #define DisplayWidth 768
#else
 #define TableViewHeight 374
 #define DisplayHeight 480
 #define DisplayWidth 320
#endif

Есть идеи?

6 ответов

Решение

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

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

if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
}
else {
}

Другими словами, после предварительной обработки у вас просто есть пустой if а также else тела.

Если вы хотите изменить значение чего-либо на основе условия во время выполнения, тогда это должно быть подлинным объектом, а не просто макросом препроцессора. Например

extern int TableViewHeight; // defined somewhere else
extern int DisplayHeight; // defined somewhere else
extern int DisplayWidth; // defined somewhere else

if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
  TableViewHeight = 916;
  DisplayHeight = 1024;
  DisplayWidth = 768;
}
else {
  TableViewHeight = 374;
  DisplayHeight = 480;
  DisplayWidth = 320;
}

#define (а также #ifdefи т. д.) обрабатываются препроцессором. Это выполняется полностью перед самим компилятором; на самом деле это два совершенно разных процесса. Так что он вообще не взаимодействует с такими конструкциями, как if,

Ваш второй пример кода может работать, если UIUserInterfaceIdiomPad это макрос (т.е. он был #defined).

#defines замещаются препроцессором до запуска компилятора. Это означает, что вы не можете установить их значение во время выполнения. То, как я могу сделать то, ради чего ты идешь, выглядит примерно так:

В вашем.h файле:

static CGFloat TableViewHeight;
static CGFloat DisplayHeight;
static CGFloat DisplayWidth;

в файле.m (реализация класса):

+ (void)initialize
{
    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
     TableViewHeight = 916.0;
     DisplayHeight = 1024.0;
     DisplayWidth = 768.0;
    } else {
     TableViewHeight = 374.0;
     DisplayHeight = 480.0;
     DisplayWidth = 320.0;
    }
}

В качестве альтернативы, вы можете сделать что-то вроде этого:

#define TableViewHeight ((UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) ? 916.0 : 374.0)
#define DisplayHeight ((UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) ? 1024.0 : 480.0)
#define DisplayWidth ((UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) ? 768.0 : 320.0)

Наконец, для DisplayHeight и DisplayWidth вам на самом деле не нужно ничего делать, и, вероятно, лучше использовать CGRectGetHeight([[UIScreen mainScreen] bounds]) а также CGRectGetWidth([[UIScreen mainScreen] bounds]),

Я думаю, что вы ответили на свой вопрос:) Однако, чтобы удалить предупреждения, почему бы не объявить их как переменные вместо макросов?

Я бы сделал это:

CGFloat tableHeight = (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) ? 916.0f : 374.0f;

Использование #if вместо нормального if,

Однако это будет препроцессор, который будет означать, что ваше приложение будет просто компилироваться только для iPhone или iPad (если оно даже работает).

Итог: нет, вы не можете использовать макросы. Они проверяются при компиляции, а не при запуске приложения.

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

Второй случай не имеет смысла, потому что вас не волнует, UIUserInterfaceIdiomPadопределяется, вас волнует, UI_USER_INTERFACE_IDIOM() имеет это значение.

Другие вопросы по тегам