如何根据设备类型定义预处理器宏?

时间:2014-07-24 09:48:48

标签: ios iphone objective-c ipad macros

我发现很多与宏相关的问题,但没有什么可以帮助我,所以请帮助我 我的问题是关于设备类型定义宏常量。

请参阅以下代码

#define IPAD UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad
#define IS_IPHONE ( [ [ [ UIDevice currentDevice ] model ] isEqualToString: @"iPhone" ] )


#if defined(IPAD)
#define SCREENWIDTH  768
#define SCREENHEIGHT 1024
#define TWIDTH 69
#define THEIGHT 69
#define BX 42
#define BY 0
#elif defined(IS_IPHONE)
#define SCREENWIDTH  320
#define SCREENHEIGHT 480
#define TWIDTH 29
#define THEIGHT 29
#define BX 16
#define BY 34
#endif

此代码在ipad上运行良好,但在iphone中返回所有ipad值?

2 个答案:

答案 0 :(得分:2)

试试这个 -

#define IS_IPAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
#define SCREENWIDTH  ((IS_IPAD) ? 768 : 320)
#define SCREENHEIGHT ((IS_IPAD) ? 1024 : 480)
#define TWIDTH ((IS_IPAD) ? 69 : 29)
#define THEIGHT ((IS_IPAD) ? 69 : 29)
#define BX ((IS_IPAD) ? 42 : 16)
#define BY ((IS_IPAD) ? 0 : 34)

这可能会有所帮助 您的代码中的问题是您正在检查宏(IS_IPAD)是否已定义,因此无论IS_IPAD的值是什么,它总是被定义,这就是为什么它不会进入else部分,因此请检查宏的值。感谢

答案 1 :(得分:2)

那是因为IPADIS_IPHONE被设计为在运行时使用,而不是编译时间,例如:

if (IPAD) {
    [self doIpadSpecificThing];
} else {
    [self doIPhoneSpecificThing];
}

他们使用#define使其更容易调用,但该定义扩展为:

if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
    [self doIpadSpecificThing];
} else {
    [self doIPhoneSpecificThing];
}

它们被设计用于可在iPad和iPhone上运行的通用应用程序,但根据它们运行的​​平台做不同的事情。

因此,您无法在编译时使用SCREENWIDTHIPAD定义IS_IPHONE等,据我所知,没有可用于测试目标iPad / iPhone的编译时宏(见TargetConditionals.h)。

编辑对已接受答案的评论:

这个答案看起来非常聪明,似乎是保存一些打字的好方法。但是我希望有人考虑使用这个答案来考虑发生了什么。

假设:

#define UI_USER_INTERFACE_IDIOM() \
   ([[UIDevice currentDevice] respondsToSelector:@selector(userInterfaceIdiom)] ? \
   [[UIDevice currentDevice] userInterfaceIdiom] : \
   UIUserInterfaceIdiomPhone)

#define IS_IPAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
#define SCREENWIDTH  ((IS_IPAD) ? 768 : 320)
#define SCREENHEIGHT ((IS_IPAD) ? 1024 : 480)

然后是SCREENWIDTHSCREENHEIGHT的典型用法:

[self setWidth:SCREENWIDTH
        height:SCREENHEIGHT];

将扩展为(类似):

[self setWidth:([[UIDevice currentDevice] respondsToSelector:@selector(userInterfaceIdiom)] ? \
   [[UIDevice currentDevice] userInterfaceIdiom] : \
   UIUserInterfaceIdiomPhone) == UIUserInterfaceIdiomPad ? 768 : 320
        height:([[UIDevice currentDevice] respondsToSelector:@selector(userInterfaceIdiom)] ? \
   [[UIDevice currentDevice] userInterfaceIdiom] : \
   UIUserInterfaceIdiomPhone) == UIUserInterfaceIdiomPad ? 1024 : 480];

现在我在该调用中看到了几个重复的方法调用,这可能不是一件好事,可以吗?

编辑2 要提供实际回答问题的内容,您可以使用接受答案中的宏,但也可以减少对UI_USER_INTERFACE_IDIOM()的调用次数。

因此,无论何时需要使用特定于平台的代码,请在开始时调用UI_USER_INTERFACE_IDIOM()一次:

BOOL isIpad = UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad;

然后根据接受的答案定义宏以使用BOOL变量:

#define SCREENWIDTH  (isIpad ? 768 : 320)
#define SCREENHEIGHT (isIpad ? 1024 : 480)
#define TWIDTH (isIpad ? 69 : 29)
#define THEIGHT (isIpad ? 69 : 29)
#define BX (isIpad ? 42 : 16)
#define BY (isIpad ? 0 : 34)

然后我给出的示例调用扩展到更合理:

[self setWidth:(isIpad ? 768 : 320)
        height:(isIpad ? 1024 : 480)];

然后每个调用方法只调用一次[[UIDevice currentDevice] respondsToSelector:],而不是每个调用参数调用一次。