iPhone - How to use #define in Universal app - iphone

I'm creating universal app that runs oniphone and ipad.
I'm using #define to create CGRect. And I want to use two different #define - one for iPhone and one for iPad.
How can I declare them so that correct one will be picked by universal app..........
I think I've to update little more description to avoid confusion.
I've a WPConstants.h file where I'm declaring all the #define as below
#define PUZZLE_TOPVIEW_RECT CGRectMake(0, 0, 480, 100)
#define PUZZLE_MIDDLEVIEW_RECT CGRectMake(0, 100, 480, 100)
#define PUZZLE_BOTTOMVIEW_RECT CGRectMake(0, 200, 480, 100)
The above ones are for iphone. Similarly for iPad I want to have different #define
How can I proceed further?

As recommended by Apple, use
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { ... }
else { ... }
to write platform-specific code. With the ternary ?: operator, you could also incorporate this into a #define:
#define MyRect (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad ? CGRectMake(0,0,1024,768) : CGRectMake(0,0,480,320))
In case you wanted to use conditional compilation to determine which of two #define statements should be included in your code, you can't: a universal app does not contain two separate binaries for iPhone and iPad. It's just one binary so all platform-related decisions have to be made at runtime.

i used this function to detect iPad, and then write conditions for all different parts of my application.
#ifdef UI_USER_INTERFACE_IDIOM
#define isPad() (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
#else
#define isPad() NO
#endif
Also you can load different xib files for iPhone/iPad.

Related

How to create if-else loop near #import sttatement to check the Device Type (iPad/iPhone)

I am using PKRevealController to create SplitView in my app. In PKRevealController.m file i am giving the value to how much screen will reveal using this code
#define DEFAULT_LEFT_VIEW_WIDTH_RANGE NSMakeRange(273, 310)
This is for iPhone but now i want to make loop to select the size. if device is iPad than large else small so how can i do this because its outside of #interface PKRevealController
I have check some code on google and i find like this
#if defined(__IPHONE_6_0) || defined(__MAC_10_8)
#define AF_CAST_TO_BLOCK id
#else
#define AF_CAST_TO_BLOCK __bridge void *
So can i create something like this for selecting device?
You can use this code to achive this change value according to your need
In your PKRevealController.m
#define DEFAULT_LEFT_VIEW_WIDTH_RANGE_iPad NSMakeRange(700, 700)
#define DEFAULT_LEFT_VIEW_WIDTH_RANGE_iPhone NSMakeRange(273, 310)
#define DEFAULT_RIGHT_VIEW_WIDTH_RANGE_iPad DEFAULT_LEFT_VIEW_WIDTH_RANGE_iPad
#define DEFAULT_RIGHT_VIEW_WIDTH_RANGE_iPhone DEFAULT_LEFT_VIEW_WIDTH_RANGE_iPhone
And in iterface find out setup method an replace it with this method
pragma mark - Setup
- (void)setup
{
self.state = PKRevealControllerFocusesFrontViewController;
if ([[UIDevice currentDevice] userInterfaceIdiom] ==UIUserInterfaceIdiomPhone)
{
//device is iPhone
self.leftViewWidthRange = DEFAULT_LEFT_VIEW_WIDTH_RANGE_iPhone;
self.rightViewWidthRange = DEFAULT_RIGHT_VIEW_WIDTH_RANGE_iPhone;
}
else
{
//device is iPad
self.leftViewWidthRange = DEFAULT_LEFT_VIEW_WIDTH_RANGE_iPad;
self.rightViewWidthRange = DEFAULT_RIGHT_VIEW_WIDTH_RANGE_iPad;
}
self.view.autoresizingMask = (UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth);
}
Than it should be work..:)
I don't really think there is a way to do that, usually problem like that is solved by making 2 #define statements, like this:
#define DEFAULT_LEFT_VIEW_WIDTH_RANGE_IPHONE NSMakeRange(273, 310)
#define DEFAULT_LEFT_VIEW_WIDTH_RANGE_IPAD NSMakeRange(273, 310)
and then when you have to use it in code just check the device type like this:
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
/* code that uses DEFAULT_LEFT_VIEW_WIDTH_RANGE_IPAD */
}
else {
/* code that uses DEFAULT_LEFT_VIEW_WIDTH_RANGE_IPHONE */
}

Custom header files in iOS Universal app

Can I do something as simple as:
myHeaderFile~iphone.h
myHeaderFile~iPad.h
and then: #import "myHeaderFile.h"
?
I'm assuming no, but you get the idea. Any tips?
If I try using macros it doesn't work, because by the time the macros are parsed, the app is already running. I just need that for loading different definitions for different screen resolutions.
How about something like this instead?
#ifdef UI_USER_INTERFACE_IDIOM()
#define IS_IPAD() (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
#else
#define IS_IPAD() (false)
#endif
Then you can selectively build code like:
if (IS_IPAD()){
// do something for iPad
}
else {
// do something for iPhone/iPod
}

ifdef syntax doesn't work

I want dynamically define a constant based on the different device heights.
I tried to use this code but it doesn't work:
#define isPhone568 ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone && [UIScreen mainScreen].bounds.size.height == 568)
#ifdef isPhone568
#define kColumnHeightPortrait568 548
#else
#define kColumnHeightPortrait568 (IS_IPAD ? 984 : 460)
#endif
Even if i'm using the 3.5" simulator, i get 548. What's wrong with this?
You can't run code in macro definitions, it's a simple text substitution process that happens at compile-time. Hence you have no idea what the device characteristics are at that point, because you're not on the target device.
If you want to use something like [UIDevice currentDevice] userInterfaceIdiom, you have to evaluate it at run-time, not in a compile-time macro, something like:
int kColumnHeightPortrait568 = 548;
if (([[UIDevice currentDevice] userInterfaceIdiom] != UIUserInterfaceIdiomPhone)
|| ([UIScreen mainScreen].bounds.size.height != 568))
{
kColumnHeightPortrait568 = (IS_IPAD ? 984 : 460);
}
The #ifdef is used to check whether a macro is defined. As you define isPhone568 in the first line, #ifdef isPhone568 will be true.
If you want to test the value of an expression rather than the existance of a macro, you should use #if instead. But #if can test no more than the simple arithmetic expression, just as paxdiablo mentioned, "You can't run code in macro definitions".

iPhone : How to check device using MACRO?

I want to check whether the device is iPhone or iPad using the macro.
I have a file Constant.h where I have given values using #define.
Now, I want to check device using #ifdef #endif.
Follwing method can be possible only in the .m file.
But I have only one .h only.
- (BOOL) isPad{
#ifdef UI_USER_INTERFACE_IDIOM
return (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad);
#else
return NO;
#endif
}
So above method is not useful for me ?
Is there any way to do this ? Or any other way?
I have simple answer to this question.
#define isiPad (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad ? YES : NO)
This will returns 1 if device is iPad and 0 if device is iPod or iPhone.
You can't check it by macro, because macro is expanded during compilation. So you need to know device type at compile time.
If you want to support both devices at runtime, you need to check device type and use appropriate set of constants.
#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 30200
UIDevice* thisDevice = [UIDevice currentDevice];
if(thisDevice.userInterfaceIdiom == UIUserInterfaceIdiomPad)
{
// etc.
}
#endif

Best way to programmatically detect iPad/iPhone hardware

The reason I need to find out is that on an iPad, a UIPickerView has the same height in landscape orientation as it does in portrait. On an iPhone it is different. The iPad programming guide introduces an "idiom" value to UIDevice:
UIDevice* thisDevice = [UIDevice currentDevice];
if(thisDevice.userInterfaceIdiom == UIUserInterfaceIdiomPad)
{
// iPad
}
else
{
// iPhone
}
which works OK while you're in iPad (3.2) but not iPhone (3.1.3) - so it looks like there also needs to be an ifdef to conditionally compile that check, like:
#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 30200
UIDevice* thisDevice = [UIDevice currentDevice];
if(thisDevice.userInterfaceIdiom == UIUserInterfaceIdiomPad)
{
// etc.
}
#endif
To me that's starting to look very clumsy. What's a better way?
Checking at runtime (your first way) is completely different from #if at compile time. The preprocessor directives won't give you a universal app.
The preferred way is to use Apple's Macro:
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
// The device is an iPad running iPhone 3.2 or later.
}
else
{
// The device is an iPhone or iPod touch.
}
Use 3.2 as the base SDK (because the macro is not defined pre 3.2), you can target prior OS versions to get it running on the iPhone.
I'm answering this now (and at this late date) because many of the existing answers are quite old, and the most Up Voted actually appears to be wrong according to Apples current docs (iOS 8.1, 2015)!
To prove my point, this is the comment from Apples header file (always look at the Apple source and headers):
/*The UI_USER_INTERFACE_IDIOM() macro is provided for use when
deploying to a version of the iOS less than 3.2. If the earliest
version of iPhone/iOS that you will be deploying for is 3.2 or
greater, you may use -[UIDevice userInterfaceIdiom] directly.*/
Therefore, the currently APPLE recommended way to detect iPhone vs. iPad, is as follows:
1) (DEPRECATED as of iOS 13) On versions of iOS PRIOR to 3.2, use the Apple provided macro:
// for iPhone use UIUserInterfaceIdiomPhone
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
2) On versions of iOS 3.2 or later, use the property on [UIDevice currentDevice]:
// for iPhone use UIUserInterfaceIdiomPhone
if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad)
I like my isPad() function. Same code but keep it out of sight and in only one place.
My solution (works on 3.2+):
#define IS_IPHONE (!IS_IPAD)
#define IS_IPAD (UI_USER_INTERFACE_IDIOM() != UIUserInterfaceIdiomPhone)
then,
if (IS_IPAD)
// do something
or
if (IS_IPHONE)
// do something else
In Swift use userInterfaceIdiom instance property as-
if UIDevice.current.userInterfaceIdiom == .phone {
print("iPhone")
}
& For other devices -
switch UIDevice.current.userInterfaceIdiom {
case .pad:
print("iPad")
case .phone:
print("iPhone")
case .tv:
print("TV")
case .carPlay:
print("carPlay")
default: break;
}
Put this method in your App Delegate so that you can call it anywhere using [[[UIApplication sharedApplication] delegate] isPad]
-(BOOL)isPad
{
BOOL isPad;
NSRange range = [[[UIDevice currentDevice] model] rangeOfString:#"iPad"];
if(range.location==NSNotFound)
{
isPad=NO;
}
else {
isPad=YES;
}
return isPad;
}
If you are using features that are not backwards compatible, I found the best way for me is to create a #define in the pre-compiled header. Example:
#if __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_3_2
#define USING_4_X
#endif
Then in your code, you can do this:
BOOL exists = NO;
#ifdef USING_4_X
exists = [SomeObject someMethod:[url lastPathComponent]];
#else
exists = [SomeObject someMethod:[[url path] lastPathComponent]];
#endif
If
1- you already have the app installed into your device,
2- you change its build settings to be a 'Universal' app,
3- install the app to your device on top of the pre-existing app (without deleting the previous one)
You might find that the solutions provided here to detect iPhone/iPad do not work. First, delete the app that was 'only' for iPad/iPhone and install it fresh to your device.
BOOL isIpad()
{
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
return YES;
}
return NO;
}
extension UIDevice {
var isIPad: Bool {
return UIDevice.current.userInterfaceIdiom == .pad
}
}