When to use "#if __IPHONE_OS_VERSION_MIN_REQUIRED > x"? - objective-c

This question addresses how to conditionally include code based on iOS version. But how does it work?
Suppose I set iOS Deployment Target to 3.2 in Xcode 4.5.2. In my code I put in some #ifdef statements:
#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0
// Some iOS 4+ code
#endif
If I run the code on a 3.2 device, this code won't be there, but if I run it on a 4.3 device, it will, right? How does that happen? Or am I misunderstanding what's going on here?

That is a compile time check so it will create the same behavior on any iOS version. Since the Deployment Target is less than 4.0 the code inside the if statement will not run on any device.
If you want the behavior you described you need to do a runtime check. You can see an example of how to do this in the thread that you linked.

Related

Why am I getting Property with 'retain (or strong)' attribute must be of object type in GCDevice.h?

My code has always compiled correctly in Xcode versions prior to 12. Now that I'm trying to build in 12 I'm getting this error - which I know how to fix, except that it's in the CoreController header, GCDevice.h, provided by Apple.
Doubly annoyingly, I'm not even using CoreController - but it's imported by GameKit.h, which I do use.
My code is written in ObjectiveC, and built for MacOS, and GameKit is imported as follows (if that makes any difference):
#import <Cocoa/Cocoa.h>
#import <GameKit/GameKit.h>
#import <AVFoundation/AVAudioPlayer.h>
When I create a completely new project, with GameKit and with only my code which uses GameKit copied and pasted into it (so not the actual game), it builds fine. Which, to my mind, suggests maybe a problem with the build settings?
GameKit is only imported once, so I don't think that there's a problem with multiple imports. Has anyone else seen this issue?
build Settings -> Depolyment -> macOS Depolyment Target -> 11.1
In my case, the answer was that there was nothing amiss with the code. For some reason the contents of the .xcodeproj file were corrupted, or different from what Xcode 12 expected, but in a way that Xcode 12 couldn't repair.
Once I cleaned out the xcuserdata from the .xcodeproj (open the xcodeproj bundle and delete xcuserdata (also from the xcworkspace bundle)), the problem disappeared.
Your mileage may vary - make sure that you have a backup before messing around in this file!
For those wanting to use an earlier Deployment version, you can (as Ma Jin answered) set the Deployment Target to 11.1 to remove the error. But then, after doing a compile, you can set the Deployment version back to the earlier version (e.g. 10.9) and it will compile also. Don't ask me why this works.

Separate code between different versions of Mac OS X?

I want some code tobe compiled under 10.6 and below but not 10.7 and above.
For example:
#ifdef current version is MAC_OS_X_VERSION_10_6 or below
// do this
elif current version is MAC_OS_X_VERSION_10_7 or above
//do that
#endif
Can someone help me ge proper macros for it? I looked into AvailabilityMacros.h but was not able to figure out proper ifdef.
I have a dynamic library, and it cannot be loaded under 10.7 and above but loads properly under 10.6. This is due to private symbol _CGContextAppendPath. I want to keep it using under 10.6 and below but avoid its use in 10.7 and below. This is because _CGContextAppendPath symbol is not present on 10.7 and above.
I used,
SInt32 version = 0;
Gestalt( gestaltSystemVersion, &version );
bool lionabove = ( version >= 0x1070 );
did not work.
For Objective C, the go-to route would be to check the availability of specific APIs via e.g. [object respondsToSelector:].
For the C library you are using, weak-link to CoreGraphics.framework (so the loading doesn't fail when some functions aren't present) and check for availability of the function in question via &_CGContextAppendPath != NULL.
Details in http://developer.apple.com/library/mac/#documentation/DeveloperTools/Conceptual/cross_development/Configuring/configuring.html#//apple_ref/doc/uid/10000163i-CH1-107837 and http://developer.apple.com/library/mac/#documentation/DeveloperTools/Conceptual/cross_development/Using/using.html#//apple_ref/doc/uid/20002000-1114537-BABHHJBC.
Apple introduced a new Availability.h macro file for iOS and Mac OS 10.6 and above (located in <SDK>/usr/include/Availability.h). You can do what you are asking like this:
#if __MAC_OS_X_VERSION_MIN_REQUIRED < 1070
// code to run up through 10.6
#else
// code to run on 10.7 or higher
#endif
Note that this macro is also available (which might be preferable depending on your logic):
#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
// code to run on 10.7 or above
#else
// code to run below 10.7
#endif
The documentation for this is here: Conditionally Compiling for Different SDKs, particularly worth looking at if you are mixing iOS and Mac OS X code. I also highly recommend reading the header file mentioned above.

How to create a 2nd app from a 2nd target in XCode?

So I created a simple project, which I can test as an iPhone app. Now I'd like to make a slight variation of it, with an iAd. I was able to duplicate the target and test to the iPhone, by managing schemes (http://developer.apple.com/library/ios/#documentation/ToolsLanguages/Conceptual/Xcode4UserGuide/Building/Building.html).
The issue is that no matter what scheme I test, I overwrite the other app. I'd like to be able to have two apps
AppName
AppName (Free)
living at the same time on my phone.
I want to avoid duplicating source files, because only the storyboard and the view controller are different, they both use the same images and model otherwise.
Any help is welcome!
Have you tried changing the bundle identifier in the new target you just created? So your full version would have bundle identifier: "com.yourcompany.AppName" and your lite version will have a bundle identifier of: "com.youcompany.AppNameLite"
I'm not currently on my Mac partition so sorry if I'm a bit off.
I would add a new configuration for your app. Call it something like "Release Free". Add a gcc preprocessor symbol "FREE" to this configuration.
Then everywhere you initialize and instantiate your iads put the code within some "#if" statements.
Something like this.
#if FREE
// Init iAds
#endif

How to check if my IOS App support IOS 3+? And something about anonymous function

I'm new to IOS development, sometimes I use a function but ignore its Doc.
So, I may use some functions are only supported on IOS 4 or even IOS 5, but I want to support IOS 3+.
Does it has any way to check if my app support IOS 3+?
I don't want to check line by line, thx.
And BTW, anonymous function like void (^ funcName)(NSString *) is objective-c feature, right? So it is supported on all IOS version, right?
Change your 'Deployment Target' to 3.x to see if any methods you're using aren't supported on that version.
That however is not a substitute for testing on 3.x; so either find a 3.x device or drop support for that version. Also, blocks (the 'anonymous function' you describe) are only available on iOS 4 and above.
If you want to write different sets of code for different version targets, you can use preprocessor directives:
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 50000
... 5.x code here ...
#elif __IPHONE_OS_VERSION_MAX_ALLOWED >= 40000
... 4.x code here ...
#else
... 3.x code here ...
#endif
Try running your app on a device running 3.x
by anonymous functions do you mean blocks like:
[self performSomeBlock:^(NSString *smth) {
NSLog(#"%#", smth);
}];
or do you mean just c like definitions (its late so i forgot the legit name)
void doSomething(void *(*func)(NSString *)) {
...
}

Xcode Objective-c Compile Time Conditional

I'm working on an iOS project in xcode and I'd like to include different codes depending on the build scheme. ie: For anything except the Distribution on an iOS Device scheme, I'd like to include a bunch of debug stuff. But for the Distribution on an iOS Device scheme, I don't want to include the debug stuff.
If I can add some sort of conditional code block it will be very helpful as it will eliminate the chance of me forgetting to change the flag manually.
Thanks!
By default when you create a new XCode 4 project it will add DEBUG to your GCC_PREPROCESSOR_DEFINITIONS (Preprocessor Macros) under build settings so you can do the following.
#ifdef DEBUG
//Debug only code here
#endif
If you need more preprocessor definitions add them under GCC_PREPROCESSOR_DEFINITIONS or OTHER_CFLAGS or OTHER_CPLUSPLUSFLAGS [prefix the last 2 with -D] for the correct build configuration.