iamVishal16
iamVishal16

Reputation: 1780

How to define preprocessor macros with respect to device type ?

I have found many questions related to macros but nothing can help me so please help me My question is define macros constant with respect to device type.

Please see below code

#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

this code run well on ipad but in iphone return all ipad values ?

Upvotes: 0

Views: 1202

Answers (2)

trojanfoe
trojanfoe

Reputation: 122458

That's because IPAD and IS_IPHONE are designed to be used at runtime, not compile time, for example:

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

They use #define to make them easier to call, but that define expands to:

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

They are designed to be used in a Universal app which work on both iPad and iPhone but do different things depending on which platform they are running.

Therefore you cannot define SCREENWIDTH etc at compile time using IPAD and IS_IPHONE and as far as I am aware there is no compile-time macros available to test for targeting iPad/iPhone (see TargetConditionals.h).

EDIT A comment on the accepted answer:

This answer looks pretty clever and seems to be a good way of saving some typing. However I would like anyone considering using that answer to consider what is happening.

Given:

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

And:

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

Then a typical use of SCREENWIDTH and SCREENHEIGHT:

[self setWidth:SCREENWIDTH
        height:SCREENHEIGHT];

Will expand to (something like):

[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];

Now I see several duplicate method calls in that call, and that cannot be a good thing, can it?

EDIT 2 To provide something that actually answers the question, you can use the macros from the accepted answer but also reduce the number of calls to UI_USER_INTERFACE_IDIOM().

Therefore whenever platform-specific code needs to be used, call UI_USER_INTERFACE_IDIOM() once at the start:

BOOL isIpad = UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad;

and then define the macros from the accepted answer to use that BOOL variable:

#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)

and then the example call I give expands to the much more reasonable:

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

and then there is only one call to [[UIDevice currentDevice] respondsToSelector:] per calling-method, instead of one per called-parameter.

Upvotes: 2

Viper
Viper

Reputation: 1408

Try this -

#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)

This may help The problem in your code is that you are checking if the macro (IS_IPAD) is defined or not, so whatever the value of IS_IPAD it is always defined, thats why its not going in else part, so check the value of macro. Thanks

Upvotes: 2

Related Questions