Will Swift Concurrency deploy back to older OSs?

I think the frustration here is because we've waited years for Swift concurrency and now it's here most developers in the real world who are not indie or work for Apple won't be able to use it and will have to wait more years knowing that any concurrency code they write now with closures etc is already technical debt.

It's also frustrating that other platforms like Android are able to update system components out-of-band, why Apple has never done this baffles me. It should't be a surprise that developers are disappointed every year at WWDC when new APIs comes out that we can't use.

32 Likes

I still have a little hope because this is listed in the "Known issues" section of Xcode 13 beta:

Known Issues

  • Swift Concurrency requires a deployment target of macOS 12, iOS 15, tvOS 15, and watchOS 8 or newer. (70738378)

If it doesn't support old versions, it will finally hurt the future of Swift itself.

We've waited for several years until so-called ABI stability. But now this is happening again in a considerably worse form: there's no way to bundle Swift stdlib to have backport support.

6 Likes

Agreed, but I wouldn't mind this at all — it's much easier to ask users on older devices that can't upgrade to the latest and greatest because their devices don't support iOS 15 to upgrade to a version that's available to them (especially if it comes with security improvements).

It definitely does complicate #available, but at this point from what we've been hearing so far adjusting #available sounds like it might be easier than the Swift team having to figure out how to backport features so that Swift devs can actually use them on a reasonable timescale.

1 Like

@matt-curtis I agree the 'ship an update to previous OS versions' is better than the current proposal. I just don't see it happening.

Going back to shipping the language runtime with the app is what has to happen, as appears to be the case on non-Apple platforms. With app thinning Apple should be able to deploy it to only those devices that need it, or, as indicated in Swift.org - Evolving Swift On Apple Platforms After ABI Stability

" Will an app built with Swift 5 run on any version of macOS before 10.14.4?

Swift 5 does not require apps to raise their minimum deployment target.

Apps deploying back to earlier OS releases will have a copy of the Swift runtime embedded inside them. Those copies of the runtime will be ignored — essentially inert — when running on OS releases that ship with the Swift runtime."

then there are 'inert' runtimes on those platforms that already support the features.

4 Likes

Looking at this from the business perspective I think features like this one aren’t created just for the internal development team but rather to improve quality of all software running on Apple platforms. Requiring this year’s OS release for this feature to work would mean that most apps will start adopting this in a few years from now.

I think it would make a lot of sense to add support for this feature (or significant subset) to apps running on earlier iOS versions (or subset if it was easier) also if the performance would be worse. Most businesses don’t need the best performing code but they require support of older operating systems.

7 Likes

That's not a bad idea, you upload your app with the latest runtime embedded, Apple apply app thinning to remove the runtime and create a binary variant which is used when users download in the AppStore on devices that already have the latest or minimum required runtime, all other users (minority) get the slightly larger non-thinned binary containing the runtime.

11 Likes

A lot of the focus here is on the developer implications of whether or not features like this get back ported. Makes sense, that's our jam, but I would argue that the user implications are more important.

Suppose you're the owner of a Mid-2014 13" MacBook Pro. MacOS Monterey drops support for this device. Unless a third party patcher becomes available, you'll be stuck on Big Sur. It's been 7 years, so that seems reasonable. Look at some of the impacts of that:

  • You won't get the new "Focus" features. (that's okay, you still have DnD)
  • Third party apps won't have access to the Focus-related APIs (they'll have to disable related features, or fallback to something else)
  • Third party apps won't have access to Swift concurrency (third party developers will need to ... ???)

One of these is not like the other. It's not like we're missing dark mode, or some theme change, or an isolated feature that can be chopped off with if #available. We're talking about a low-level, prevailing source code feature that's impossible (for practical purposes) to conditionally use.

There's a diversity dimension that I'm particularly concerned about: economic status. It's one whose importance seems (to me) to be clear as day, but I don't really see anyone championing for it. We forget that most people aren’t cycling their expensive tech like us, as though they were some baller annual subscription service. Indeed, iPhone software longevity is a large selling feature, and a competitive advantage of the platform compared to the fragmented Android ecosystem. Moves that go against this just end up being anti-poor (intentionally or not), obsoleting older/second-hand devices.

I can remember a few instances on other platforms (particularly Android) where a single release had so many improved APIs/features that they caused a major turning point. Companies with a policy of say, supporting 3 years back, made exceptions and ended up only supporting 2 years back, just to rush to get to this good stuff.

Every time that happens, we (the dev community) form a thundering herd that leaves poor users behind. We should make sure there's a good reason for it, and I think it's important to do whatever we can to not force the hand of third party devs to drop support for OSes. If Java/Mono/Go could figure this out, I think we should, too.

29 Likes

Very well said, thank you for writing this.

It would be amazing if this backport is made possible. I'm definitely willing to volunteer if any work is needed to make this happen.

SwiftUI came out two years ago, but I haven't touched it because I have to support iOS 12.

I don't want to be left out of concurrency. I have lots of RxSwift code that uses Single that can be much better expressed with async/await.

7 Likes

this is highly disappointing. Going to take years to adopt now. Can we simply have an option to link the needed "runtime support" with the app???

2 Likes

Windows and Linux have nothing to worry about here, as they aren't ABI stable and can easily move to the latest language version whenever they need. It's strictly Apple's platforms where this is a concern, as they include Swift as part of the OS.

4 Likes

After just watching the excellent WWDC session by @Ben_Cohen (Swift concurrency: Update a sample app - 10194) its been made very obvious that by not having the ability to back-port Swift concurrency by even a single major iOS version is a multiplying problem across the industry.

Let's take our team of 15 iOS devs as an example. We currently support iOS 13 as our minimum deployment target and have over 220k swift LOC in the app. The minimum deployment target is dictated by our users upgrade behaviour, so as it stands we won't be able to drop iOS 14 until iOS 17 is out. In that time a lot more code will be produced that can't adopt Swift concurrency and we are possibly looking at double or more lines being added to our codebase over that time.

The problem is that the more code we add over that time the more time it's going to take us to adopt async/await and the harder sell it's going to be to the business to have time to make those changes. It's been made very obvious in Ben's talk that this isn't going to be a trivial conversion and will take a long time to adopt.

All the time we spend writing code for the next two+ years we know at some point we are going to have to do some major refactoring. So then comes the question; should we just continue to use GCD and pretend swift concurrency doesn't exist for the lifetime of the app? From a business point of view the time we spend actually fixing concurrency issues right now pales in comparison to refactoring the entire codebase to adopt Swift Concurrency in a few years time, and that balance won't actually shift for a long time. This is something that will be echoed across the industry, hence the multiplier I mentioned before.

I think the Swift concurrency features are great and I've personally played with a few of the early snapshots, so it came as quite a surprise that it wasn't being supported on older iOS versions. I have a feeling that we have missed the boat already to get this changed for the release of iOS 15, but it's worth saying that if this could be supported for even 1 previous major iOS version then it is going to save many thousands of hours of developer time over the coming years.

18 Likes

All of your users are able to update to iOS 15 on day 1, so you're in a much better situation than anyone supporting iOS 12 or macOS. macOS is really the big issue here, as the machines last much longer and are more expensive (usually) than mobile devices.

5 Likes

Windows and Linux have nothing to worry about here, as they aren't ABI stable and can easily move to the latest language version whenever they need. It's strictly Apple's platforms where this is a concern, as they include Swift as part of the OS.

Good to know that its an ABI problem. Was afraid that this would became a bigger issue

Need to take a time to update the swift compiler source and see how is this whole concurrency plumbing is going under the hood..

I'm afraid about exactly this, that the user upgrade behaviour can be changed, by holding the developer experience hostage, and weaponizing third-party app support as leverage to entice users to buy new hardware more often.

That's the road I hope we don't keep going down.

5 Likes

I'll throw in my two cents as someone working on a framework: Having a language feature that's only available on the newest OSes is going to be a huge pain, both internally and externally.

We'll likely need to create a secondary library that makes various public APIs available as async/await for people who want to use that, but leaves completion handlers for people who don't. That's a pretty significant maintenance burden.

We'd also love to take advantage of the simplifications and correctness helpers of this internally, but if we can't do that for older OSes, then for all intents and purposes, we can't do that at all. Frankly, I was really looking forward to async/await and its ability to vastly simplify a bunch of our callback-based code, but without some kind of runtime helper we wouldn't be able to do this for years. That's a big disappointment.

It's been mentioned previously, but I do think the Android Support libraries are a good pattern to consider here: They allow backporting of new features to old operating systems, and allow developers to continue to support older OSes while taking advantage of improvements in developer experience included in new ones. You also only have to add the support libraries to your application or framework if your API target is below what's supported natively - once you drop support for older OSes, you can remove that extra code entirely.

Obviously not needing that would be even better, but I'd way rather have an extra library than be unable to use and have to do a ton of extra work to support async/await on older versions.

16 Likes

Back when Swift 5.0 was first announced with ABI stability on Apple platforms, we wrote a blog post outlining some of the reasons the Swift runtime cannot be embedded in apps anymore:

Can I choose to bundle a newer Swift runtime with my apps going forward to be able to use new runtime features without requiring a new OS?

This will not be possible for a number of reasons:

  • The coexistence functionality that is used to maintain compatibility with pre-stable Swift runtimes depends on there being no more than two Swift runtimes active in a single process, and that all Swift code using the pre-stable runtime is self-contained as part of the app. If the same mechanism were used to allow a newer Swift runtime to be bundled to run alongside the OS Swift runtime, the new runtime would have no access to Swift libraries in the OS or ABI-stable third-party Swift libraries linked against the OS runtime.
  • Outright replacing the OS runtime with a bundled runtime would circumvent the security of the system libraries, which are code-signed based on their using the OS version of the runtime.
  • Furthermore, if the OS Swift runtime could be replaced, this would add a dimension to the matrix of configurations that the OS, Swift runtime, and third-party libraries and apps all have to be tested against. “DLL hell” situations like this make testing, qualifying, and delivering code more difficult and expensive.
  • By being in the OS, the Swift runtime libraries can be tightly integrated with other components of the OS, particularly the Objective-C runtime and Foundation framework. The OS runtime libraries can also be incorporated into the dyld shared cache so that they have minimal memory and load time overhead compared to dylibs outside the shared cache. Eventually, it may be impossible for a runtime built outside the OS to fully replicate the behavior of the OS runtime, or doing so may come with significant performance costs when constrained to using stable API.

Hopefully that helps answer some of the questions about why back-deploying concurrency is not a mere matter of bundling a new runtime with old OSes.

47 Likes

With all due respect, this never covered how, why not, etc… the OS component could not be updated outside of the OS updates themselves. It requires a lot of work that could have been spent in other areas and it was sorely needed because as a platform Android is so so fragmented, but Google Play Services being updated and delivering core libraries updates through the Play Store, with more and more OS components delivered through the Play Store too (project Mainline not unlike Treble before it), are not just medicines against fragmentation but a big help to developers overall.

I think this thread could be a good opportunity for bringing these discussions and the compromises (nothing is perfect :)) made along the way forward again: as a dev I see Compose and Kotlin async/await and async sequences (Flow) and I can back deploy to Android 5, while SwiftUI’s latest big updates and async/await in Swift are iOS 15 only. Same thing for WKWebView improvements vs Android System WebView/Chrome WebView (the latter updated on the Google Play Store… ok sometimes causing massive breakages).

I do see also the ugly side of Jetpack libraries approach because the burden is on the dev to figure out how these hundreds of libraries work together (makes updating and dependency management fun). Apple going that far may be a bit of a “Frogs who wished for a king” tale… ;).

This is aside from how it is getting more and more complex to update macOS versions in an Enterprise settings which might bite people when a future Xcode update mandates Monterey next April or May (I worked quite a bit with our IT to get my team updated to Big Sur, the rest of the company aside from few people in IT may have to wait for Monterey as Big Sur was a bigger break for vendors we depend on than I was hoping especially for updates and not clean installs, but sorry this is beside the point… but if Sophos Endpoint Security, Global Protect VPN, Cisco Umbrella/OpenDNS, JAMF, etc… are not bringing memories… well, I am genuinely happy for you :)).

8 Likes

Just to throw my hat in the ring here, I am also in the position of not being able to use anything tied to iOS 15 specifically, for at least two years and maybe longer...

I know it's a hard problem to figure out how to back port this, but being able to do anything (even just part of Swift Concurrency and not the whole thing?) would be welcome, even just to iOS 14 and above would be a great help.

That said this is an important enough change I am considering getting buy-in to ship iOS15 specific versions of an SDK my company publishes, so that all of the interfaces would be Swift Concurrency friendly.

3 Likes

While true, it doesn't mean that they will. There is a long held perception that upgrading will slow down their devices. This is no longer the case for the most part, but it's a hard perception to break. For us as an e-commerce app, we can't simply drop an OS if we have an insignificant number of users using an older version of the OS, our users will simply go elsewhere.

I do feel for anyone who has a lower minimum deployment target than even we do, or even those who support macOS in this situation. We are in a more fortunate position but are still several years away from adopting this technology.

This is pretty much what I thought, and why I realise its probably too late in the day to change/adopt anything before Swift 5.5 drops later this year. It would be nice to see if there are any recommended strategies for the thousands of developers who can't adopt this right now but want to in future?

7 Likes