#ifdef conditionals not working - iphone

I am using conditional code as below,
I want to run certain code only in ios5.0 and > ios5.0( i mean i want to support ios5.0 and 5.1 version too)
But the below condition dos not seem to work. ( Currently my development version is 5.1 but the below snippet is not getting identified.the control is not going into it.)
Please let me know your thoughts
#ifdef __IPHONE_5_0_OR_LATER

#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_5_0
// iPhone 5.0 code here
#endif
#define __IPHONE_2_0 20000
#define __IPHONE_2_1 20100
#define __IPHONE_2_2 20200
#define __IPHONE_3_0 30000
#define __IPHONE_3_1 30100
#define __IPHONE_3_2 30200
#define __IPHONE_4_0 40000
#define __IPHONE_4_1 40100
#define __IPHONE_4_2 40200
#define __IPHONE_4_3 40300
#define __IPHONE_5_0 50000
#define __IPHONE_5_1 50100
#define __IPHONE_NA 99999 /* not available */
How to target a specific iPhone version?

#ifdef is a compile directive, thus it will be evaluated at compile time not run time.
Thus if you add this to you code, the methods call in the if will all ways be called if your target SDK matches your #ifdef. So if you compile an app for both iOS 4 and 5 and place all the 5 only methods in #ifdef io5 the app will crash on iOS 4 since the methods will be called.
If you want to check if some method is available then you should do like :
Here is an example for dismissing an modal view controller from it's parent. Since parentViewController is changed to presentingViewController in iOS 5, we check if presentingViewController is available and use it.
if ([self respondsToSelector:#selector(presentingViewController)]) {
[self.presentingViewController dismissModalViewControllerAnimated:YES];
} else {
[self.parentViewController dismissModalViewControllerAnimated:YES];
}
The same with goes for checking if a class is available :
if ([MPNowPlayingInfoCenter class]) {
MPNowPlayingInfoCenter *center = [MPNowPlayingInfoCenter defaultCenter];
NSDictionary *songInfo = /* ... snip ... */;
center.nowPlayingInfo = songInfo;
}

NSArray *versionCompatibility = [[UIDevice currentDevice].systemVersion componentsSeparatedByString:#"."];
if ( 5 == [[versionCompatibility objectAtIndex:0] intValue] ) { /// iOS5 is installed
// Put iOS-5 code here
} else { /// iOS4 is installed
// Put iOS-4 code here
}

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

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

Check iOS version at runtime?

This is sort of a follow on from my last question. I am using beginAnimations:context: to setup an animation block to animate some UITextLabels. However I noticed in the docs that is says: "Use of this method is discouraged in iOS 4.0 and later. You should use the block-based animation methods instead."
My question is I would love to use animateWithDuration:animations: (available in iOS 4.0 and later) but do not want to exclude folks using iOS 3.0. Is there a way to check to iOS version of a device at runtime so that I can make a decision as to which statement to use?
Simpler solution for anyone who'll need help in the future:
NSArray *versionCompatibility = [[UIDevice currentDevice].systemVersion componentsSeparatedByString:#"."];
if ( 5 == [[versionCompatibility objectAtIndex:0] intValue] ) { /// iOS5 is installed
// Put iOS-5 code here
} else { /// iOS4 is installed
// Put iOS-4 code here
}
In many cases you do not need to check iOS version directly, instead of that you can check whether particular method is present in runtime or not.
In your case you can do the following:
if ([[UIView class] respondsToSelector:#selector(animateWithDuration:animations:)]){
// animate using blocks
}
else {
// animate the "old way"
}
to conform to version specified in system defines
//#define __IPHONE_2_0 20000
//#define __IPHONE_2_1 20100
//#define __IPHONE_2_2 20200
//#define __IPHONE_3_0 30000
//#define __IPHONE_3_1 30100
//#define __IPHONE_3_2 30200
//#define __IPHONE_4_0 40000
You can write function like this
( you should probably store this version somewhere rather than calculate it each time ):
+ (NSInteger) getSystemVersionAsAnInteger{
int index = 0;
NSInteger version = 0;
NSArray* digits = [[UIDevice currentDevice].systemVersion componentsSeparatedByString:#"."];
NSEnumerator* enumer = [digits objectEnumerator];
NSString* number;
while (number = [enumer nextObject]) {
if (index>2) {
break;
}
NSInteger multipler = powf(100, 2-index);
version += [number intValue]*multipler;
index++;
}
return version;
}
Then you can use this as follows:
if([Toolbox getSystemVersionAsAnInteger] >= __IPHONE_4_0)
{
//blocks
} else
{
//oldstyle
}
Xcode 7 added the available syntax making this relatively more simple:
Swift:
if #available(iOS 9, *) {
// iOS 9 only code
}
else {
// Fallback on earlier versions
}
Xcode 9 also added this syntax to Objective-C
Objective-C:
if (#available(iOS 9.0, *)) {
// iOS 9 only code
} else {
// Fallback on earlier versions
}
Most of these solutions on here are so overkill. All you need to do is [[UIDevice currentDevice].systemVersion intValue]. This automatically removes the decimal, so there is no need to split the string.
So you can just check it like:
if ([[UIDevice currentDevice].systemVersion intValue] >= 8) {
// iOS 8.0 and above
} else {
// Anything less than iOS 8.0
}
You can also define a macro with this code:
#define IOS_VERSION [[UIDevice currentDevice].systemVersion intValue];
or even include your check:
#define IOS_8PLUS ([[UIDevice currentDevice].systemVersion intValue] >= 8)
Then you just need to do:
if (IOS_8PLUS) {
// iOS 8.0 and above
} else {
// Anything less than iOS 8.0
}
Discouraged is not the same as deprecated.
If you need to support earlier versions of iOS that do not have the block based methods, there is nothing wrong with using the older methods (as long as they haven't been removed, of course).
You can use the version of the Foundation framework to determine the current system version.
if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_6_1){
//for earlier versions
} else {
//for iOS 7
}
For my purposes I've written a tiny library that abstracts away the underlying C calls and presents an Objective-C interface.
GBDeviceDetails deviceDetails = [GBDeviceInfo deviceDetails];
if (deviceDetails.iOSVersion >= 6) {
NSLog(#"It's running at least iOS 6"); //It's running at least iOS 6
}
Apart from getting the current iOS version, it also detects the hardware of the underlying device, and gets info about the screen size; all at runtime.
It's on github: GBDeviceInfo. Licensed under Apache 2.
Put this in your Prefix.pch file
#define IOS_VERSION [[[[[UIDevice currentDevice] systemVersion] componentsSeparatedByString:#"."] firstObject] intValue]
And then you can check iOS versions like:
if(IOS_VERSION == 8)
{
// Hello 8!
}
else
{
// Hello some other version!
}
Off course if you can use feature detection (and it makes sense for your use case) you should do that.
In MonoTouch:
To get the Major version use:
UIDevice.CurrentDevice.SystemVersion.Split('.')[0]
For minor version use:
UIDevice.CurrentDevice.SystemVersion.Split('.')[1]
A bit nicer and more efficient adaptation to the above solutions:
-(CGPoint)getOsVersion
{
static CGPoint rc = {-1,-1};
if (rc.x == -1) {
NSArray *versionCompatibility = [[UIDevice currentDevice].systemVersion componentsSeparatedByString:#"."];
rc.x = [versionCompatibility[0] intValue];
rc.y = [versionCompatibility[1] intValue];
}
return rc;
}
now you can
if ([self getOsVersion].x < 7) {
}
HTH

Target iPhone Simulator Macro Not Working

Using the TARGET_IPHONE_SIMULATOR macro results in the same constant values being defined in am application. For example:
#ifdef TARGET_IPHONE_SIMULATOR
NSString * const Mode = #"Simulator";
#else
NSString * const Mode = #"Device";
#endif
- (void)applicationDidFinishLaunching:(UIApplication *)application
{
...
NSLog(#"Mode: %#", Mode);
...
}
Always results in "Mode: Simulator" being logged. I'm currently running XCode 3.2.4 if that helps. Thanks.
TARGET_OS_SIMULATOR is defined on the device (but defined to false). The fix is:
#include <TargetConditionals.h> // required in Xcode 8+
#if TARGET_OS_SIMULATOR
NSString * const Mode = #"Simulator";
#else
NSString * const Mode = #"Device";
#endif
Not sure when this was changed. I'm fairly sure it was possible to use 'ifdef' in the past.
For me explicitly including TargetConditionals.h helped
#include <TargetConditionals.h>
Try TARGET_OS_SIMULATOR, as TARGET_IPHONE_SIMULATOR is deprecated.
I would try implement macro if its going to be used on different classes through out the app.
in pch file ,
#if TARGET_IPHONE_SIMULATOR
#define isSimulator() YES
#else
#define isSimulator() NO
#endif
and in any class I can check by calling isSimulator().
For some reason TARGET_IPHONE_SIMULATOR doesn't work for me in xcode v6.4 . The snippet below works perfectly :
#if (!arch(i386) && !arch(x86_64))
camera = Camera()
#else
camera = MockCamera()
#endif
Swift:
#if targetEnvironment(simulator)
showSimulatorOnlyError()
#endif