Joris Kluivers

I like to build software.

Future Proofing: Calling New APIs on Old Devices

When building applications you’ll eventually have to deal with different versions of the OS or availability of features. Adoption of a new iOS version is usually pretty fast, but uptake for a new version is still measured in months. And even after an OS upgrade, some features might never be available because of hardware limitations.

The easy solution is to just limit your app to certain hardware or OS versions. Better of course is to support new features when available and fallback or leave those features out on older OS versions and older hardware.

Read more below about methods to deal with new API’s on older devices.

Target the right SDKs

To start with there are two options in your build settings you want to make sure are configured correctly.

note: while this post targets iOS, this strategy applies equally well to Mac OS X SDKs

  • Base SDK - The SDK you’re building your application against. Set this to Latest iOS.
  • iOS Deployment Target - The minimum version your application should work on.

By using the Latest iOS value for your Base SDK you make sure all the latest symbols are available at compile time. The strategies below are performed at runtime on the actual device and will work on older OS versions too.

Checking for new C constants

1
2
3
if (&UIKeyboardFrameBeginUserInfoKey != NULL) {
  // Use this constant
}

UIKeyboardFrameBeginUserInfoKey is defined as a NSString *const (a pointer). By asking for the memory address to the value of this constant, you’ll know if it is defined on the current OS. Because you built against the latest SDK this location will point to a real value on any OS that implements this key. However on older OSs that location will point to NULL.

Checking for new C functions

1
2
3
4
if (UISomeNewMethod != NULL) {
  // call function
  UISomeNewMethod();
}

Similar to checking for C constants above.

Checking for new methods on classes

1
2
3
4
SEL sel = @selector(scale);
if ([UIScreen instancesRespondToSelector:sel]) {
  // scale factor available
}

Checking if a class is available

1
2
3
4
Class kvsClass = NSClassFromString(@"NSUbiquitousKeyValueStore")
if (kvsClass) {
  // iCloud class available
}

Of course if you are checking for classes in a linked framework, and the framework did not exist on older iOS versions, you want to weak link your frameworks to prevent a crash.