Supporting Multiple iOS Versions and Devices

There are many different iOS versions and devices out there in the wild. Supporting more than just the latest is often necessary since not all users upgrade immediately. This tutorial shows you how to achieve that goal. By Pietro Rea.

Leave a rating/review
Save for later
Share
You are currently viewing page 6 of 6 of this article. Click here to view the first page.

Supporting Multiple Devices

This tutorial has only covered backwards compatibility as it relates to software; however, making sure your apps can run on a wide range of hardware is just as important.

The obvious hardware differences between the iPhone and the iPad won’t be covered in this tutorial. However, check out the tutorial on porting an iPhone app to iPad and the one on updating your apps to the 4-inch iPhone 5 display since they are related to the topic of supporting multiple devices.

The idea behind maintaining backwards compatibility in hardware is simple: iOS devices can have (or lack) a variety of different hardware components. Just as you performed a runtime check to verify if a particular API was available, you have to perform a runtime check to see if a hardware component is available before you attempt to use it.

But what if the device doesn’t have the hardware you need for your app? If a particular hardware component is absolutely crucial to your application, it’s best if you limit the distribution of your application to devices that have such components. Can you imagine installing a flashlight app on a device with no camera flash?

You can specify the hardware features required by your app by changing the UIRequiredDeviceCapabilities key in your project’s Info.plist. Click on your target and navigate to Info/Required device capabilities, as shown below:

RWRageFaces 21

The UIRequiredDeviceCapabilities key lets you include or exclude device capabilities such front camera, back camera, camera flash, GPS, magnetometer, gyroscope, Bluetooth and more. Refer to Apple’s Information Property List Key Reference Guide and for a full list.

Note: Right-click on the project’s Info.plist and choose Open As > Code to edit the UIRequiredDeviceCapabilities key. The array value will suffice if you just want to list required capabilities. However, if you want to state both required capabilities and capabilities that devices must not have, then you can convert it to a dictionary. Then you use true or false values for each device capability to indicate which capabilities are required and which must not be present.

When a hardware component is not critical to your application, you may choose to hide or disable it if the component is not present. For example, you can use the following two methods to check if a device has a back or a front camera:

    if ([UIImagePickerController isCameraDeviceAvailable:UIImagePickerControllerCameraDeviceRear]) {
        //safe to use back camera
    }
    
    if ([UIImagePickerController isCameraDeviceAvailable:UIImagePickerControllerCameraDeviceFront]) {
        //safe to use front camera
    }

isCameraDeviceAvailable: is available as of iOS 4.0. You have to do a few additional checks if your deployment target is earlier than iOS 4.0, which should be unlikely at this point!

UIImagePickerController is also helpful for checking if your camera has flash capabilities and video recording capabilities.

To check if your device supports a microphone, use the following AVFoundation API:

    AVAudioSession *session = [AVAudioSession sharedInstance];
    if (session.inputIsAvailable) {
        //safe to use microphone
    }

inputIsAvailable is deprecated as of iOS 6. Use inputAvailable instead if your deployment target is iOS 6 or above.

Additionally, you can use Core Motion’s CMMotionManager to detect if your device has a gyroscope, a magnetometer or an accelerometer.

    CMMotionManager *motionManager = [[CMMotionManager alloc] init];
    
    if (motionManager.gyroAvailable) {
        //safe to use gryoscope
    }
    
    if (motionManager.magnetometerAvailable) {
        //safe to use magnetometer
    }
    
    if (motionManager.accelerometerAvailable) {
        //safe to use accelerometer
    }

gyroAvailable and accelerometerAvailable are available as of iOS 4. magnetometerAvailable, on the other hand, is available as of iOS 5. To check for a magnetometer prior to iOS 5, use CLLocationManager‘s headingAvailable API, which is available in the Core Location framework.

There are a few more hardware components you could check for that haven’t been covered here. The main takeaway, however, is that you should never assume that a particular hardware component is present on a device, as that assumption might not hold true for older devices — or for newer ones!

Device Collection Winners

As promised, here are the coolest iOS collections from users that responded to Ray’s tweet.

Longest straight line (@libovness):

largest_straight_line

Most beautiful Collection (@blakespot):

Biggest collection (@_DavidSmith):

biggest_collection

Having your own collection of test devices is not only cool to look at, but is really helpful during development and testing.

Where To Go From Here?

Congratulations! You’ve succesfully navigated the art and science of backward compatibility on iOS. Here is the completed RWRageFaces project — fully compatible on iOS 5 and iOS 6.

Even though the tutorial dealt mainly with iOS 5 and iOS 6, the techniques presented here such as runtime checks, introspection and weak linking will be useful for many more iOS versions to come.

Always keep in mind that not everyone is a power user. If you pay close attention to backwards compatibility, your users will definitely thank you for making sure your applications are well supported on whichever system they are running.

Contributors

Over 300 content creators. Join our team.