You've likely seen the news: Apple has told some iOS developers that it will disallow new purchases of some apps in the App Store within 30 days. It's easier to quote the Email than to describe it:
App Store Improvement Notice
This app has not been updated in a significant amount of time and is scheduled to be removed from sale in 30 days. No action is required for the app to remain available to users who have already downloaded the app.
You can keep this app available for new users to discover and download from the App Store by submitting an update for review within 30 days.
If no update is submitted within 30 days, the app will be removed from sale.
The letter does not define a "significant amount of time," does not explain why some apps are not affected, and does not specify how this “improves” the App Store.
Unsurprisingly, coverage of this development is universally negative. At The Verge, opinions range from “mobile apps should remain available no matter their age” to “the policy is unnecessarily tough on developers” before broadening to consider the possibility that “Apple doesn’t fully respect the work that goes into indie games.” (Citations in the original article—go read it.)
On the other hand, inside the Apple ecosystem, coverage is…also uniformly negative. Nick Heer at pixel envy writes:
There does not appear to be a reason why these apps are being culled now, so it appears to be just because Apple thinks the App Store needs cleaning up and, hey, some users and developers are going to suffer. Good luck to all the indie developers being forced to create a new build of their app just because.
Here is a perceptive commentator and a daily read here. And he’s right: since Apple has not explained, there does not appear to be one. At Daring Fireball, John Gruber notes there have been reasons in the past for these transitions (“like the 32-bit to 64-bit transition”) before noting that some apps are, well, complete:
I get the feeling this has a particularly heavy cost for indie game makers — and, ultimately, the players and would-be players of their games. We can watch really old movies today — movies that aren’t just years or decades old, but generations old. We can read works of literature that are centuries old. But we can’t play iPhone games that are three years old unless the developers constantly devote time and attention to making sure they keep up with latest SDKs every 2-3 years? Pixar doesn’t have re-render Toy Story every couple of years.
This is so close to getting it that it would be painful if this part were not even closer:
But in practice, there are a lot of apps that haven’t been updated in a while that continue to run just fine. It’s often not just a matter of opening a project file in Xcode and recompiling to get a new build. Sometimes you open an older project and it takes a lot of work to get it to recompile against the current SDKs.
And there’s the unasked question someone needed to answer: why would it take a lot of work to recompile against a current SDK?
Can We Carry That Baggage For You?
When developers build apps, those apps are put together using (or “linked against”) a specific version of the iOS Software Development Kit. Each SDK version targets a particular version of iOS. Developers can tell Xcode to use both minimum and maximum version targets for their app. By rule and default, the maximum version of the SDK is the one that’s current for that version of Xcode at the time of linking.
The minimum version is up to the developer, within limits. If a developer sets a minimum supported version of, let’s say, iOS 11, then Xcode will build an app that will launch on any version between iOS 11 and the current version of iOS. It’s up to the developer to ensure that the app does not try to use iOS 12 or iOS 13 features when running on iOS 11.
But what happens if a given part of the OS changes between versions of iOS? Perhaps we should pick an example, such as a change in networking made in the iOS 13 SDK:
Starting with iOS 13 beta 4, the copy attribute of the
httpBodyStream
property ofNSMutableURLRequest
is enforced. If the body data is mutated after the property setter has been called, data sent in the HTTP request won’t include that mutation. Invoking the property getter no longer returns aNSMutableData
reference, even when the setter was invoked with data of that type. As of iOS 13 beta 5, apps built using the iOS 12 SDK or previous SDKs use the legacy behavior.
You don’t need to care what this API does. The emphasis we added to the last sentence is the important part. Imagine a company whose app targets iOS 12 and uses this attribute of the NSMutableURLRequest
API. If that company updates its build machine to use the iOS 13 SDK, it will get new behavior in its app.
If the app depends on the old behavior, it may break in iOS 13—but if it changes to rely on the new behavior, won’t it break on iOS 12? It wouldn’t matter in this API’s case, but it might break for others with similar changes, right?
That’s what the emphasized text is all about. As long as the developer keeps using a build system that stops at iOS 12, the app will not link against the iOS 13 SDK and gets the old “legacy” behavior, not the new behavior that matches what the documentation always said.
How? Because iOS 13 includes both behaviors. As long as the OS detects that your app didn't use the iOS 13 SDK or any newer one, it sets it on a backward-compatible path. That might involve loading different libraries at runtime on the iOS device, taking a different path inside the core OS, or even patching the app while loading it to maintain new binary compatibility. Apple does not describe how it works or promise that it will always work the same way, just that it works.
Every version of iOS contains boatloads of these multiple-version workarounds. They’re not hard to find, either. Apple has not yet deprecated the CFMessagePortSetName
function, but starting in iOS 12, it no longer does anything. Until iOS 15, key commands for iPad hardware keyboards took precedence over typing in text fields, and it still happens that way—unless the app links to the iOS 15 or newer SDK. Every year at WWDC, we hear about changes to iOS user interface elements that would screw up existing apps, so Apple maintains the older appearance for apps that don’t link against that year’s new SDK.
On and on it goes across hundreds if not thousands of APIs multiplied by each new iOS version. Remember the great Scott Forstall-era iOS design change from gray buttons with shapes to simple blue text? All the iOS 6-and-earlier UI code stayed in iOS at least until the 64-bit transition. That update required linking to the iOS 11 (or later) SDK, but allowed targeting iOS 6 and later as long as the developer acknowledged that the code would get iOS 7-and-later UI elements on those versions of the operating system.
That’s why updating an old app takes more than recompiling. Until this month, Apple required all app submissions to link against the iOS 14 SDK. That jumps to a minimum of the iOS 15 SDK starting this month, released last September. (All iOS SDK versions require a version of Xcode no earlier than the one released with that SDK version—in this case, Xcode 12 for the iOS 14 SDK and Xcode 13 for the iOS 15 SDK.) Developers who haven’t touched their apps in years must address the changes over the years in iOS, including working around APIs that no longer exist. It’s not easy.
The Technical Debt Ceiling
The aforementioned 64-bit transition supported five previous iOS releases, covering iOS 6 through 11. We’re now 39 days away from WWDC 2022 and the bankable announcement of iOS 16. If we adopt a similar timetable, it might suggest that iOS 16 could support apps linked against the iOS 11 or later SDKs. iOS 11 was released on 19 September 2017—probably five years before any iOS 16 release.
iOS 6, in turn, was released on 19 September 2012 to accompany the iPhone 5, a model three years older than the earliest models that iOS 15 supports. We think it’s entirely fair for Apple to say, at some point, “We’re not going to support apps that link against an iOS SDK made for phones the OS no longer supports.”
Apple has not said this, at least not that we can find, and that’s probably part of why the move to drop “outdated” apps from the App Store seems capricious and short-sighted. We strongly suspect that if you could look at data for all the apps scheduled for removal, you’d find that they all linked against something older than the iOS 12 SDK, or maybe even older than the iOS 11 one.
We’d go even further: with WWDC starting soon, we have no difficulty speculating (and it is speculation, to be sure) that Apple has begun running compatibility tools against the database of iOS app binaries, seeing which ones are using APIs or entire OS system that the company no longer wants to build, maintain, test, and support in iOS.
Technical debt describes the cost of not making software changes that you know you should make because they’re too difficult or expensive. Today, iOS carries the technical debt for thousands of applications that did not keep up with changes in the OS. At some point, that debt has to devolve back onto the developers that didn’t make changes, rather than accumulating on Apple because it updated and modernized the operating system.
Apple has been better on backward compatibility than most of its competitors, but everything has limits. The new Mac Studio does not run the original MacPaint binary—nor will it run any PowerPC binaries (a feature lost 11 years ago in Mac OS X 10.7), and only runs Intel binaries through Rosetta 2 translation. iOS in turn dropped support for 32-bit binaries nearly five years ago. It’s unreasonable to require a major hardware change to allow iOS to shed years of patches to benefit developers who haven’t kept up.
Is this unfair to apps that were complete years ago, like games? Others made the point that Gruber expressed most succinctly: “Pixar doesn’t have re-render Toy Story every couple of years.” That’s true, but the VHS tape of Toy Story you bought in 1996 does not work on your Apple TV box attached to your 8K TV. You can watch it on that TV with a VCR, but then again, that’s the device for which that tape was designed and on which you intended to play it. If you want the 4K HD version, you have to buy it—and you can, because Pixar did the work to create that version.
If developers cannot do the same because their apps were complete when released for iOS 11, you can keep an older device running iOS 11.
We’re not promising more issues, but we had something to say here.
Old apps may die, but I'm glad to see that MDJ lives on. Welcome back!