Использование макроса (Определение) в операторе if/else ? Без переопределенной ошибки

#ios #objective-c

Вопрос:

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

Таким образом, это фактически временная мера! У меня есть пара определенных макросов,

 #define BTNNUMBER_W         60
#define BTNNUMBER_H         60 
 

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

 if(IS_IPHONE_OLD)
    {
    #define BTNNUMBER_W         60
    #define BTNNUMBER_H         60
    }
    else if (IS_IPHONE_5)
    {
    #define BTNNUMBER_W         60
    #define BTNNUMBER_H         60
    }
    else if (IS_IPHONE_6_6S_6P_6SP_7_8)
    {
    #define BTNNUMBER_W         30
    #define BTNNUMBER_H         30
        NSLog(@"iPhone 6 to 8");
    }
    else if (IS_IPHONE_7P_8P)
    {
    #define BTNNUMBER_W         60
    #define BTNNUMBER_H         60
        NSLog(@"iPhone 7P to 8P");
    }
    else if (IS_IPHONE_X)
    {
    #define BTNNUMBER_W         110
    #define BTNNUMBER_H         110
    }
 

Как уже было сказано, на самом деле это просто для того, чтобы снова «заставить его работать», пока я все это переделаю, но любые указатели будут мне очень признательны!

 #define IS_IPHONE (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
#define IDIOM    UI_USER_INTERFACE_IDIOM()
#define IPAD     UIUserInterfaceIdiomPad


#define SCREEN_WIDTH ([[UIScreen mainScreen] bounds].size.width)
#define SCREEN_HEIGHT ([[UIScreen mainScreen] bounds].size.height)
#define SCREEN_MAX_LENGTH (MAX(SCREEN_WIDTH, SCREEN_HEIGHT))
#define SCREEN_MIN_LENGTH (MIN(SCREEN_WIDTH, SCREEN_HEIGHT))

#define IS_IPHONE_OLD (IS_IPHONE amp;amp; SCREEN_MAX_LENGTH == 480.0)
#define IS_IPHONE_5 (IS_IPHONE amp;amp; SCREEN_MAX_LENGTH == 568.0)
#define IS_IPHONE_6_6S_6P_6SP_7_8 (IS_IPHONE amp;amp; SCREEN_MAX_LENGTH == 667.0)
#define IS_IPHONE_7P_8P (IS_IPHONE amp;amp; SCREEN_MAX_LENGTH == 736.0)
#define IS_IPHONE_X (IS_IPHONE amp;amp; SCREEN_MAX_LENGTH == 812.0)
 

Ответ №1:

В C и Objective-C используйте препроцессор #if , а не язык программирования if :

 #if IS_IPHONE_OLD || IS_IPHONE_5
#define BTNNUMBER_W         60
#define BTNNUMBER_H         60
#elif IS_IPHONE_6_6S_6P_6SP_7_8
#define BTNNUMBER_W         30
#define BTNNUMBER_H         30
// …
#endif
 

Однако это не сработает, потому что ваши IS_IPHONE_OLD и т. Д. Не являются константами времени компиляции (и не могут быть, так как одно и то же приложение может быть запущено на нескольких телефонах). Препроцессор выполняет простую замену текста, и все это происходит еще до того, как какой-либо код будет проанализирован (следовательно, препроцессор).

Вы не можете влиять на макросы препроцессора во время выполнения, но вы можете знать только размер экрана во время выполнения…

Вместо этого переключите макросы на переменные с тем же именем:

 CGFloat BTNNUMBER_W;
CGFloat BTNNUMBER_H;
 

А затем в какой-либо функции, которая запускается до их использования, назначьте их значения:

 if (IS_IPHONE_OLD || IS_IPHONE_5) {
   BTNNUMBER_W = 60;
   BTNNUMBER_H = 60;
} // …
 

В качестве альтернативы назовите свою переменную чем-нибудь более приятным, а затем:

 #define BTNNUMBER_W ([[AppDelegate instance] buttonNumberWidth])
 

В Swift используйте вычисляемые свойства:

 static var buttonNumberWidth: CGFloat {
    let screenWidth = UIScreen.main.bounds.size.width
    if screenWidth <= 480 {
        return 30
    } // …
}
static var buttonNumberHeight: CGFloat { buttonNumberWidth }
 

Комментарии:

1. Так что, если я использую этот метод; #if IS_IPHONE_OLD || IS_IPHONE_5 #define BTNNUMBER_W 60 #define BTNNUMBER_H 60 #elif IS_IPHONE_6_6S_6P_6SP_7_8 #define BTNNUMBER_W 30 #define BTNNUMBER_H 30 #elif IS_IPHONE_7P_8P #define BTNNUMBER_W 30 #define BTNNUMBER_H 30 #endif Макрос по какой-то причине невидим, и Use of undeclared identifier 'BTNNUMBER_W' позже в коде, из которого на него ссылаются, появляется ошибка, должно ли сначала быть пустое определение вышеупомянутого? Перед использованием препроцессоров?

2.TBH неясно, что именно вы пытаетесь сделать, поскольку IS_IPHONE_OLD это не константа времени компиляции. Можете ли вы отредактировать вопрос, чтобы показать, как именно IS_IPHONE_OLD он определен? Я подозреваю, что причина, по которой нет макроса, заключается в том, что у вас нет ни одного из IS_IPHONE_OLD #define d в препроцессоре, и у вас нет #else предложения для определения чего-либо в этом случае.

3. Моя вина! Действительно, я забыл #else в конце макросов! Спасибо, это сработало именно так, как мне было нужно!

4. @DannyRoy Если это сработало с тем #else , то происходит то, что результатом всегда является только #else часть. Так что вы могли бы заменить все это просто #define BTNNUMBER_W 60 без всяких #if «с».