ifdef syntax doesn't work - iphone

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".

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 */
}

Define constant based on device type

I have a Constants.h file which contains some global constants in fact. Since my application is built both for iPhone and iPad, i would like to define the same constants (ie with the same name) differently for the two device types.
For a complete explanation:
/******** pseudo code *********/
if (deviceIsIPad){
#define kPageMargin 20
}
else {
#define kPageMargin 10
}
How can I do this?
Thanks.
L.
It's impossible to get device type during preprocessing step. It is determined dynamically during runtime. You have two options:
Create two different targets (for iPhone and iPad respectively) and define macro there.
Create macro that inserts expression like this:
#define IS_IPAD (UI_USER_INTERFACE_IDIOM()==UIUserInterfaceIdiomPad)
#define kMyConstant1 (IS_IPAD ? 100 : 200)
#define kMyConstant2 (IS_IPAD ? 210 : 230)
#define kMyConstant3 (IS_IPAD ? #"ADASD" : #"XCBX")
#define are resolved at compile time, ie on your computer
Obviously, you can't make them conditional the way you want. I recommend creating static variable and setting them on the +(void)initialise method of your class.
And for the condition, use something like
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
// iPad
} else {
// iPhone or iPod touch.
}
So that would go
static NSInteger foo;
#implementation bar
+(void)initialise{
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
// iPad
foo = 42;
} else {
// iPhone or iPod touch.
foo = 1337;
}
}
#end
Use UIDevice Macros - http://d3signerd.com/tag/uidevice/
Then you can write code like;
if ([DEVICE_TYPE isEqualToString:DEVICE_IPAD]) {
}
or
if (IS_SIMULATOR && IS_RETINA) {
}
You can't do this with defines, as they're expanded at compilation time. However, you can define variables and set their initial value based on the user interface idiom:
// SomeClass.h
extern CGFloat deviceDependentSize;
// SomeClass.m
- (id)init
{
// ...
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad])
deviceDependentSize = 1024.0f; // iPad
else
deviceDependentSize = 480.0f; // iPhone
// etc.
}
Hi write this code in appdelegate class
+(NSString *)isAppRunningOnIpad:(NSString *)strNib{
NSString *strTemp;
NSString *deviceType = [UIDevice currentDevice].model;
if ([deviceType hasPrefix:#"iPad"]){
strTemp=[NSString stringWithFormat:#"%#I",strNib];
}
else{
strTemp=strNib;
}
return strTemp;
}
call this from your class using this line
SecondVC *obj_secondvc = [[SecondVC alloc] initWithNibName:[AppDelegate isAppRunningOnIpad:#"SecondVC"] bundle:nil];

How to build app with iOS 5.0 methods for iOS 4.3?

I'm finishing iCloud feature for my app and can't solve one problem:
Since I'm using some new 5.0 features like NSFileCoordinator, I can't build my app for 4.3 because of "dyld: Symbol not found: _OBJC_CLASS_$_NSFileCoordinator".
How can I "untarget" some files (which have iCloud methods) for building 4.3 version?
Thanks in advance!
Have a look at this.
Class cls = NSClassFromString (#"NSFileCoordinator");
if (cls) {
// Create an instance of the class and use it.
} else {
// Alternate code path to follow when the
// class is not available.
}
Also check this answer to see why
you should avoid relying on the version string as an indication of device or OS capabilities.
To just take them out of the source copilation:
Click on your project file.
Go to "Build Phases".
Expand "Compile Sources".
Select the file you dont want, and press the "-" button at the
bottom of the section.
Or you can delete it from the project (just remove the reference rather than deleting the file), and it will remove it from this section as well.
Or you could create preprocessor macros to check to see if the user can run the functions
// System Versioning Preprocessor Macros
#define SYSTEM_VERSION_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedSame)
#define SYSTEM_VERSION_GREATER_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedDescending)
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedDescending)
/* Usage
if (SYSTEM_VERSION_LESS_THAN(#"4.0")) {
...
}
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"3.1.1")) {
...
}*/
With this, you can check to see what systen version the user is using and only build for 5.0, but put in functioning code for if it is a version less than 5.0.
I think it's better to turn off iCloud feature for 4.3 builds altogether. You can do that by check iOS version at runtime. In your particular case you could check for presence of NSFileCoordinator class with NSClassFromString() function, but I'm pretty sure there are more decent ways on the internet of accomplishing this.
You could make a new build target and set a compiler preprocessing Macro like NO_CLOUD and then use
#ifdef NO_CLOUD
... code here ...#else
... cloud code here ... #endif
You have to weak link to the framwork's (when you add a framework to the project just set it as optional not required).
In the h file you have to import only if you have ios 5
#if defined(__IPHONE_5_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_5_0
#import <Twitter/Twitter.h>
#import <Accounts/Accounts.h>
#endif
and in the m file you have to try to create class from string and test to see if you have the class. And also test top see if the class responds to selectors.
Class TWTweetComposeViewControllerClass = NSClassFromString(#"TWTweetComposeViewController");
if (TWTweetComposeViewControllerClass != nil) {
if([TWTweetComposeViewControllerClass respondsToSelector:#selector(canSendTweet)]) {
UIViewController *twitterViewController = [[TWTweetComposeViewControllerClass alloc] init];
[twitterViewController performSelector:#selector(setInitialText:)
withObject:NSLocalizedString(#"TwitterMessage", #"")];
[twitterViewController performSelector:#selector(addURL:)
withObject:url];
[twitterViewController performSelector:#selector(addImage:)
withObject:[UIImage imageNamed:#"yourImage.png"]];
[self.navigationController presentModalViewController:twitterViewController animated:YES];
[twitterViewController release];
}
} else {
//do something else
}
My example is based on twitter engine you have to adapt it to your classes.
Build it with latest SDK (5.0). It will tun both 4.3 and 5.0
And you can check IOS version
if ([[UIDevice currentDevice] systemVersion] floatValue] >= 5.0f) {
// iCloud
} else {
// iCloudless
}

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

iPhone - How to use #define in Universal app

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.