Though I will probably always regard it as reeking of code smell, I have to admit that there are times when one has to write device-specific logic based on the current device’s hardware identifier. I’m referring to the identifier obtained using
sysctl(). For example, the iPhone 4S has the identifier
A good example of a valid case for device-specific code is any app that has custom AirDrop features. For example, OvershareKit has to know whether or not the current device supports AirDrop when populating the list of available services for a share sheet. Since Apple provides no APIs for checking the availability of AirDrop, our only recourse is to maintain an exhaustive list of all hardware identifiers for devices that support AirDrop.
But AirDrop is only one use case among many. Lots of apps run into situations where code really needs adapt to the capabilities of the current device. Shoehorning the same code into a ever-widening array of devices results in compromised user experiences for either the oldest or the newest devices, or both. Last year’s iPod touch and the iPhone 5S are two devices that both run iOS 7.1, but with vastly different performance characteristics.
The deeper problem is that basing device-specific logic on hardware identifiers is an indirect solution. What developers really want to know about are the characteristics of the current device, not what kind of device it is. This will be even more true if (as?) Apple’s iOS lineup branches into new device categories (cars, TVs, and watches, to name a few).
A better solution would be for Apple to provide a hypothetical
UIDeviceCharacteristics framework, which would abstract out specific characteristics like graphics performance, brute computing power, hardware features, etc. This way developers could write code that targets stable and meaningful device characteristics, instead of brittle and incomplete lists of device identifiers.