From the app developer perspective, it's really Apple's fault; they push HARD to force upgrades:
- Hardware DRM is used to block installation of old OS releases, mandating that developers maintain a stable of old hardware that they never reinstall just to be able to test on iOS < $current.
- Critical security updates aren't provided for previous major releases if the device can run the next major release. iOS 6 was left with completely broken SSL certificate validation, and the last iOS 7 release also has known bugs; the only way to get a fix is to upgrade to iOS 8.
- Apple rapidly deprecates and removes old SDKs and toolchains from Xcode long before the devices supported by them have reached their end of useful life -- for example, dropping armv6 entirely due to clang having a litany of armv6 codegen bugs. The standard test framework -- OCUnit -- was deprecated in favor of an almost identical (but API incompatible) XCTest framework ... but Apple didn't bother to port XCTest for iOS 6 and (iirc) 7.0 devices, leaving developers with the choice of breaking testing on previous releases, or disabling/ignoring deprecation warnings and just being forced to refactor all their tests at an unexpected future date when Apple will drop OCUnit without additional warning.
Apple used to have a great backwards compatibility story; now, they're shoving both developers and users as hard as they can, and leaving an enormous amount of prematurely useless hardware and artificially enforced codebase bitrot.
What's worse is that Apple's pace is producing some seriously broken, buggy OS releases. Apple needs to return to the fundamentals of driving adoption by providing the best possible platform, rather than twisting and shimmying as fast as they can to stay just out of reach of the competition.