I’ve struggled to find a way to deduce if an iPhone OS device has the ability to make phone calls or not. There is a way to do so in iPhone OS 3.0, but I want to compile my code against the OS 2.0 SDK to enable it to run on as many devices as possible.  I could just check if the device is an iPod Touch or an iPhone, but who knows what weird and wonderful iPhone OS-based devices Apple might release in the future, and I’d like my check to be future-proof.  So I’ve come up with a hybrid way of detecting the device’s ability to make calls.  This post describes the approach I’m using.

iPhone OS 3.0 introduced a new method for the UIApplication class, called canOpenURL. This method enables you to check if the current application can open a particular URL, and by extension whether it can handle a particular URL schema.

Phone calls on the iPhone OS are instigated in code by using the tel: schema, as shown below.

UIApplication *app = [UIApplication sharedApplication];
[app openURL:[NSURL URLWithString:@"tel:+44-1234-567890"]];

So on OS 3.0, we use canOpenURL to check if the application can open a sample telephone URL via the tel: schema.

On iPhone OS 2.x, we don’t have canOpenURL, and so we fall back to using the model property of [UIDevice currentDevice] to detect if the device is an iPhone or not. It’s safe to assume that any as-yet-unannounced iPhone OS devices will run OS 3.x or later, and so this provides a future-proofed test for any new devices.

Here’s the complete function I use to perform the check:

- (BOOL)deviceCanMakePhoneCalls
{
    BOOL canMakePhoneCalls;
    if ([UIApplication instancesRespondToSelector:@selector(canOpenURL:)]) {
        // OS 3.0+, so use canOpenURL
        UIApplication *app = [UIApplication sharedApplication];
        canMakePhoneCalls = ([app canOpenURL:[NSURL URLWithString:@"tel:+44-1234-567890"]]);
    } else {
        // OS 2.x, so check for iPhone
        UIDevice *device = [UIDevice currentDevice];
        canMakePhoneCalls = ([device.model isEqualToString:@"iPhone"]);
    }
    return canMakePhoneCalls;
}

This code will compile for any version of the iPhone OS SDK from 2.0 upwards, and has been tested on SDK 3.0. If you compile on an SDK version earlier than 3.0, you may see compilation warnings for the canOpenURL line; these can safely be ignored, as this code will only be triggered when it is run on a device with OS 3.0 or later.