I would like to write an app which can be run on iOS 3.1.3 up to iOS 4.1. I know how to set up the deployment target and the base SDK.
After reading the Apple docs it heavily relies on checking if the class is available and/or if an instance responds to a specific selector.
Now my questions:
- What happens if Apple made a class public from 3.1.3 to 4.x ? When just checking for the class name it would be available on iOS 3.1.3, too? So on this version I would be using a private API, which I do not want. How would you check that? Is this really a problem or am I worrying too much?
- Would you also use preprocessor symbols, which are defined by the iOS version?
- Which architecture should I choose armv6 or armv7? I think armv6 runs on armv7 as well, is that correct?
- Do I get any help from the compiler if I am using something in my code that is not available in iOS 3.1.3? Does it get checked?
- Are there any prominent pitfalls I should know about?
I already watched session 130 of WWDC10 "Future-proofing your app" so the things said there are known.
Thank you.
On (3) in isolation: there's no need to pick, just produce a fat binary with both ARM6 and ARM7 code, which is the default behaviour anyway. Whether to use thumb instructions depends on what your program does most of the time — ARMv6 Thumb doesn't contain floating point operations, so there's a substantial cost for floating point maths there. Conversely, if you're not doing very much floating point maths at all then it's much smarter to leave thumb mode on and save on memory bandwidth and cache size. ARMv7 Thumb contains floating point operations.
In your project: check out the 'Architectures' setting. It'll likely be 'Standard (arm6 arm7)', which will produce the fat binary.
To set Thumb mode (or any other setting) per architecture, select it in your Target Info window, click the little cog in the bottom left and choose 'Add Build Setting Condition'. You can then set the value that applies for that setting for a particular combination of SDK and architecture. So if you're differentiating by target CPU family then you want to do that twice, adding one value for 'Any SDK' with 'ARMv6' and one for 'Any SDK' with 'ARMv7'.
One thing to note: you can't use preprocessing symbols because those are resolved at compile time. So, if you compile your app against the 3.1.3 frameworks, you can't use the 4.0 frameworks, even on devices running 4.0 (or 4.1, currently). Personally, I solved this by making two targets.
Based on personal experience, may not have all the right answers, but I'll try:
I don't think this is a problem because of the reasoning behind the private API ban. Apple prohibits private APIs (at least in part) because they do not want things to change behind the scenes in future versions of iOS, since it is now public API, it is guaranteed to be supported.
No clue. I've seen them used for code that can run on OSX and iOS.But I don't think I would because iOS version is detected at run time and compiling can really only account for OS X vs iOS, not 3.x vs 4.x.
Go with armv6 so you can support older iOS devices. It will not be a problem with armv7. I believe that you are right that armv7 can run apps built for armv6, but I am not sure.
It depends on your target deployment platform. You do get warnings if you call deprecated code.
Probably. I've had issues with iAd, but I don't remember specifics. Just check for existing classes and remember to do your weak-linking and class-instantiation where necessary.