How to make an iPhone app compatible with multiple SDK (firmware) versions - iphone

With iOS 4 coming out soon, I have already planned to include an iAd in a future update of an app of mine. I assume that this will make my app unusable for anyone on a firmware lower than 4.0. Is there a way to change those variables and the .xib file based on the user's firmware?

Yes, you can build with the latest SDK (ie: 5.1) and still run on devices with earlier versions of the firmware (SDK).
Set your Deployment Target to the earliest version you want to be able to run with, ie: 3.0.
You set your Base SDK to the latest version that you are compiling with, ie: 5.0. This way you can reference the newer definitions and symbols in your code. This article "SDK and Deployment Targets" discusses Deployment vs Base SDK in detail.
Weak link to the libraries/frameworks with symbols that are only available in the newer iOS. This is so your app will run on a device that doesn't have the newer symbols.
You must check to see that a newer method is available before calling it. You have to make sure not to call a method that is 5.0 or 4.X only when your app is on a < 4.0 device. Of course you have to gracefully handle working on older versions by either using older methods or not supporting particular features that need newer SDK support.
NEW w/XCode 4.2: To support older devices you need to add armv6 to the build architectures and remove armv7 from the plist of required device capabilities.
See these SO questions and answers for more details:
deployment target vs base/active sdk
recommended way to support backward compatibility
How do you optionally use iPhone 3.0 features in a 2.0 compatible app
iPhone dev weak link framework
weak linking with IB
universal iphone/ipad app compilation error
iphone apps should include armv6

Related

iOS app downgrade compatibility requirements

I was wondering if it's possible to downgrade an app from the app store (ARM binary) to a lower version. For example if the app requires iOS 5.0 or 4.3 or later getting it to run on iOS 4.2 or 4.0.
I understand that the requirements are important as the newer version contains API linked calls only exposed on the newer iOS platform. However, I've many apps that are cabable of running on lower versions are needlessly compiled on newer versions of xcode (just a minor update supports a huge jump on iOS supported version, like iOs 4.0 -> iOs 5.0)
What I would like to do is maybe downgrade an iOS 5.0 app to iOS 4.3 app by verifying that there are no new linked functions apis and thereby adjusting the plist files to the lower vesion? Can otool or class-dump help with this?
Yes, it's possible. Submit a binary with a different "iOS Deployment Target" (in Project > Info and Targets > Deployment Target), even if it is lower than the one you currently have.
You'll need to do extensive testing to make sure your code runs on the various compatible iOS, since a lot has changed with the release of iOS 5 (and subsequently, 6), meaning a lot of functions and methods will not be recognized in those iOS versions.
Regarding finding which API's may not work, here's a small discussion of [Finding unsupported API's with OS version][1]
[1]: finding unsupported apis with os version "Finding unsupported API's with OS version".

How can I support both iOS 4.X SDK and iOS 5 SDK in my iPhone app?

I am writing an iPhone app in which I want to support the largest user base possible at this point in time (with minimal pain), so I decided that targeting IOS 4.3+ would be a good subset of users for my audience.
I started working in XCode 4.2, but reverted back to XCode 4.1 when I realized that the project templates had changed and everything seemed very intertwined with storyboarding, ARC, etc.
I have built out my application to the point I actually want to test on my device, which has iOS5 installed. When I attempt to use it though, I get this message as soon as I click 'use for development' in Organizer/XCode:
The project's build settings look like this:
My Question Is This: How do I get this application, built in XCode 4.1, to run on both iOS 4.3 and iOS 5 phones?
Are iOS SDKs not backward compatible? I come from Android development in which a less than current SDK will generally work on a newer SDK - is this different in the iOS world? And if so, how is this handled typically?
Any direction on how I should proceed would be greatly appreciated.
You can go ahead and open your app in Xcode 4.2 and it should still work. I've been working on a particular app since Xcode 3.x days and I'm nearly done, chugging along in Xcode 4.2 right now. It shouldn't be a problem. If you want to work with Xcode 4.1 you will be fine, but you won't be ale to use new features introduced in iOS 5.
There are several aspects of "cross-version" development to note.
Testing: You can only test on version of iOS that are included with your SDK, or that are installed on physical devices that you may have. The SDK generally comes only with the latest iOS, sometimes the previous one is included as well, but since Xcode 4 was released, the older SDKs have been progressively deprecated with each release. This is not to say that your app which is linked against the iOS 5 SDK won't run on older versions of iOS. It just depends on how you implement new features.
Features: In order to support older versions of iOS properly, you want to make sure that you don't implement new features without properly checking for the existence of classes, methods, and properties that were introduced in the newer versions of the OS. Unlike Android, you don't have to worry about a million hardware configurations. ;-)
Weak Linking: To support a new feature and still be compatible with older versions of iOS, you need to weak link against frameworks that you are using to implement new features. You can read more about that in the Apple Documentation on Weak Linking.
Deployment Target: The setting that prevents the app from loading on older devices is called the "Deployment Target". If you set this to 3.1.3, then your app will run on iOS 3.1.3 and higher. Remember that if you don't code the the proper version checking, your app may break.
ARC: You can choose to enable or disable Automatic Reference Counting when you create the project. ARC scans your program at compile time only, not at runtime, it doesn't break the app on older versions of the OS.
You need the latest version of XCode and the iOS SDK to install your apps onto your iOS 5.0 phone. That doesn't mean the inverse is true -- you don't need the same version of iOS on your device that you have installed on your computer.
Hope this helps!
You can use the latest SDK and simply set the "IOS Deployment Target" version to 4.3 in the project build settings.
XCode 4.1 doesn't support iOS5 in the sense that Xcode package doesn't contain the iOS5 SDK. So you must return to Xcode 4.2 and target your project for iOS 4.3 (you can also target it for iOS 4.0 with this Xcode version, but you will not be able to simulate it; you can even download older iOS 4.x package versions from the Xcode preferences menu if you really need to simulate them in your device).
You can opt-out of ARC if you want, this choice is given to you when you create the project, so don't worry; but consider that ARC does its magic at compile time only, not at runtime, so your backward compatibility will be kept if you decide to use this technology. Finally if you don't want Storyboard just pick the Empty app template and it will simply put in your project only the basic files. From this template you can create any iOS app, this is the approach I normally follow.

Which version of the iPhone SDK should I use for an OS4 app?

I'm wondering if I will have compatibility issues with OS4.0 if my app is built with the 4.1 SDK, or is this a non-issue?
The short answer to your question is: Use a Base SDK Version of at least 4.0 for your application and a Deployment Target Version of exactly 4.0.
I've downvoted both answers because they are wrong or at least incomplete.
When building applications there are two settings that you should be aware of:
There is the Base SDK Version which defines against which version of the SDK your application will be compiled.
There is also the Deployment Target Version which defines the lowest version of the iOS that your application requires. You can set this to as low as 2.2.1 in Xcode but the App Store will not accept versions lower then 3.1.3 at the moment.
The Base SDK Version can be higher then the Deployment Target Version. This simply means that your application is backward compatible with older version of the iOS. This also means that your app needs to make decisions at runtime to be sure not to use newer functionality when running on an older version.
For example, the MFMessageComposeViewController was introduced in 4.0 so if your app has been configured to also run on 3.1.3 then you should use NSClassFromString() to find if that specific class is actually available before you use it.
There are many questions here on Stack Overflow on how to discover available functionality so I will not repeat those techniques here.
And a somewhat important note:
Behaviour does change across OS releases. There were a pile of changes in 3.0 (we had issues with UITableView/UITableViewCell):
Some changes happened on old apps (e.g. compiled for 2.2.1). I forget what these were.
Some of them were in the toolchain (I think they changed how nibs were compiled with ibtool; it was something like setting both an image and a custom view for a UITableViewCell). This happened when we upgraded the SDK on the build server, even if we didn't touch "Base SDK"
Some of them happen only when you compiled with a Base SDK of 3.0 (UIKit automagically detects which version you've linked against and has backwards-compatability modes for some things)
Additionally, there were some runtime/C++ changes in GCC 4.2, which meant a GCC 4.2 app running on OS 2.2.1 crashed when casting unsigned int/long to float/double or using std::ostringstream. I've since added a check for GCC version.
So no, compiling with a newer SDK can result in issues — you might not want to risk it if there are time constraints (you don't have time to implement multitasking support, or you don't have time to do a complete re-test and fix all the bugs, or so). Or maybe you still want to support 2.2.1 for some strange reason (4.0 dropped 2.x "device support", which effectively made it impossible to debug apps on 2.x devices).
Usually nothing breaks across minor OS releases (discounting 3.1/3.2). I'd recommend upgrading SDKs as soon as you have the time; don't shy away from new features just because old OSes don't have them.
Depending on the APIs you will be using. Let's say you want to implemented in-app texting (MFMessageComposeViewController) and want ALL of your end-users (will be defined as EUs) to access that feature then you'll have to compile against iOS 4.0. But let's say you want the in-app texting to be optional and a "plus" for your EUs, you'll just compile your app against iOS 3.0 (let's say).
Hope I answered your question :-)

iAd and iphone before 4g compatibility

iAd seems to require iphone os 4.0, so I install the new beta ver xcode and sdk.
It works.
But The previous sdk disappear.
Now, the new build app (with iAd) is also retro compatible with 3.1.x? Or with iAd I have to renounce to retro compatibility?
You should use the standard method of building a single binary which can take advantage of features available in newer OS versions only, but still run on older OS versions too: build the application with Base SDK set to 4.0, and the Deployment Target to a lower OS version, for example 3.0. The frameworks available only in the newer OS versions should be weakly linked and the application should then check at runtime which features are available (iAd for example) and act accordingly.
See Apple's on example on how to do this: http://developer.apple.com/iphone/library/samplecode/MailComposer/Introduction/Intro.html.
iAd doesn't work with previous version (before 4.0)
I found a solution in adwhirl.
So I put inside my app adwhirl. I put admob, adsense or other circuit and iad.
I weak link in xcode project the iad framework, and adwhirl understand if iad is supported, so if ok iad appear else other circuit work!
When xCode 3.2.3 is officially released you will be able to build to previous versions again, however iAd will probably not compile on pre 4.0 builds.

Base versus Active versus Deployment target

I know that parts of this question was asked in several variation but I want to make sure I got it right.
Here are my assumptions and understandings which I want to know if they are correct before submitting.
My application assumes features supported by all OS, and so I should:
Set the Active SDK to be the latest (currently SDK 3.0).
Set the Deployment Target to be the lower I want to be supported - iPhone 2.0 and higher?
What exactly is the Base SDK for? should I ignore it if I chose Active SDK to be different and where do I see the Active SDK in the Projects settings?
One final question - is apple allowing to choose iPhone OS 2.0 as the Deployment Target?
Thanks in advance,
BTW - one of my main reason for this question is because when compiling with earlier SDKs apple seems to have a problem releasing the memory for UIImageView animation array when this animation was saved for multiple time usage. This is a known problem that was fixed with SDK 3.0 (by simply setting the UIImageView animation array to nil)
The difference between the Base and Active SDK is that the former is the default SDK set for the project and the latter is the SDK you are currently building against. So it is possible for your Active SDK to be the Base SDK, at which point XCode will use the SDK you specified for the project.
In order to build your app for the widest set of devices possible, you are correct:
Set the Base SDK to the lastest SDK possible (3.0, 3.0.1)
Set the Deployment Target to the earliest SDK possible (2.0)
Apple does allow you to specify iPhone 2.0 as the Deployment Target, but keep in mind any API or framework released after iPhone 2.0 you will not have available to you for use by default. There are techniques to use features from later SDKs, however they are nontrivial.
You should set the Base SDK build setting to the latest SDK that contains all of the features that you intend to use (usually, the latest available SDK), and set the "iPhone Deployment Target" build setting to the earliest version of the OS on which you want to run.
You then need to make sure that you check, at runtime, for any features that may not exist on the earlier OSes.
"Base SDK" is the Maximum SDK you application can support. There's a hard limit here - you can't select a future, unreleased SDK.
"Deployment Target" is the Minimum SDK you are willing to support. It how far back in time you are willing to go.
Xcode appear to create a spurious dependency on "Deployment Target." For example, I can't develop on my iOS 5.1.1 iPod with Xcode 4.5.2 (Xcode 4.5.2 is paired with iOS 6.0), even though the 4.3, 5.0, and 5.1 APIs and Simulators are installed on this installation. I need to use the simulator or jack in my iOS 6.0 iPhone.
The games Apple is playing appears to be causing problems with apps, too. My purchased copy of Elements will not sync via iTunes to the iPod because Elements needs a newer version of iOS to run (it syncs and runs fine on my iOS 6.0 iPhone).
I've got two iPads and one is 4.3. I shudder to think what a mess it will cause.
In general;
Set the BASE SDK to the very latest SDK you are willing to support and test.
Set the Deployment Target to the lowest version of iOS you are willing to support and test.
If you happen to use Base SDK features not available on the deployment target SDK, the app will crash at runtime on older devices, so testing is vital.
An alternative / complementary process would be to use Deploymate http://www.deploymateapp.com/ which does static code analysis to identify problems.
If you are from the android world the analogies are such;
TargetSDK -> Base SDK
MinSDK -> Deployment Target
Lint -> Deploymate