Just like every year, Apple announced the new versions of their operating systems during WWDC in June. Also just like every year, there were betas available for download shortly after the announcment. And also just like every year, those betas aren't bug free nor should one rely too much on them. So far so good.
While this year was generally no exception to this process, the chaos that was came along the management of these betas this year, was unlike everything I've witnessed so far. And one big part of this chaos is caused by SwiftUI and Combine. Don't get me wrong, those frameworks are awesome and have great potential. What I don't like is the way they were (and still are) developed. But let me explain a little more.
With Swift Evolution Apple has a way to manage the continuously increasing demand of new and improved features of their programming language Swift. Not too long ago, they further restricted the proposals in Swift Evolution, requiring them to have an implementation ready. Note, that Swift Evolution is mostly a public process. It involves a public discussion in the Swift Forums. Later in the process, there's a private discussion where the Swift Core Team discusses the change and makes a decision about whether it's going to be added to Swift or not. This has worked well for the last few Swift releases. Also, this caused changes to Swift to be more stable once they make it into the first beta of Xcode. Partially also, because they were tested with snapshots from the master branch before.
Now what's different this time? With Xcode 11, or more precisely with or "for" SwiftUI and Combine, there were addtions to Swift that did not go through the normal Swift Evolution process before making it into the language. Again, don't get me wrong, those changes are really nice features and I still love where the language is going. But with those features taking a "shortcut", a lot of the problems of this year's betas began.
Let's take the new "Property Wrappers" as an example. They introduce a really cool way of "wrapping" a value within a certain container, whilst not having to deal with the container itself too much. A few common such containers are Lazy
, Atomic
, Box
, etc. I think many projects had one or the other container implementation. Personally, I've even tried to achieve something similar to "Property Wrappers" inside my FFFoundation framework. Now, with Swift 5.1, creating such property wrappers became a piece of cake. Slapping an annotation to the container type and possibly renaming a few properties and initializer and that's it. There is really a lot of potential on them. But they also demonstrate clearly the overall chaos that is present in this year's betas. In the first beta, it's normal to have bugs. And so I wasn't surprised at all that the property wrappers didn't yet work perfectly. However, the property wrappers were one of a few additions to Swift this year, that have not yet gone through Swift Evolution. But they are necessary in a very substantial way for the two new Swift frameworks SwiftUI and Combine. To be honest, I don't know exactly when the corresponding proposals for those features were effectively created. I think some of them existed (be it in a more verbose form) before the keynote of WWDC. But their process started after the first beta. And with it came a lot of problems. During the public and later private discussion, the naming of the underlying property of a property wrapper was adjusted many times. So was the naming of the initializer and the annotation that has to be applied to the type. In a effort to be backwards compatible, the old naming was supported for a few releases. Even worse, some of the frameworks weren't adjusted in time, so that certain betas shipped with outdated frameworks - throwing warnings that only confused developers.
What I've described here using the new property wrappers basically applies to almost many other new features in Swift as well (namely opaque return types and function builders). Whilst being extremly cool, they went backwards through the normal process resulting in many adjustments and also an unstable final state. In the example of property wrappers, this means that they are currently extremly limited. Many important fixes didn't make it in time for the version of Swift 5.1 that is shipped with Xcode 11 anymore. With SwiftUI and Combine having to adjust to all these changes, they were partially distracted from making important fixes to the core functionality of these frameworks. Which now results in (IMHO) buggy and only partially stable/usable releases of these frameworks.
Adding to this (more Swift related) chaos, there's the chaos that was introduced when Apple started to distribute an iOS 13.1 beta while iOS 13.0 was not even in GM state. There were reasons for that, sure, but still it doesn't help the quality of this year's betas. To make things worse, this years OS release schedule is scatterd like nothing I've ever witnessed. Apple has split off iPadOS from iOS to distinguish the OS of their iPads more clearly from those of the iPhones. Which is a totally valid decision and was necessary to further improve the iPad experience. But similar to tvOS, iPadOS is still based on iOS (or its core part so to speak) and I would have expected it to be released in a very similar schedule to tvOS and iOS. But I was wrong. This year, all of Apple's OS's are released on a different date (tvOS being the only exception as far as I can tell). iOS is released first, then watchOS, then iPadOS, then macOS. This makes it extremely hard to plan releases for software that runs on more than just one of those OS's.
I'm usually responsible for updating the open source and closed source frameworks of our company (as well as some of our client projects) to new versions of Swift. And basically every year I start with this task before the GM seed is available - mainly because I enjoy working with the new features and also because I know how important early feedback is for fixing bugs and making things more stable. But this year, while I still started early, I quickly gave up trying to keep up to date. With basically every new Xcode beta, something new broke and most old bugs weren't fixed - or at least not completely. Part of me thought "well, maybe there's too much going on this year. Just wait until the GM comes around and see what features actually make it in there". So I did and the GM came. But not only was there already a second GM seed of Xcode (which is not wrong but still doesn't usually happen), but the features included feel as incomplete as they usually do in the midst of beta testing. It's not unusual that I encounter bugs in the GM seed. Some of them I knew from previous betas, some were new. And that's fine. But the number of bugs I encountered this year is enourmous. For basically every new Swift and OS feature I used in the code bases I migrated, I found multiple bugs. Of course, they're all not going to be fixed in the initial release of Swift 5.1 / Xcode 11. There are usually workarounds, of course, but in the cases I've encountered they severly limit the use of the new features. Which is not as bad for closed scope/source projects where the limitations imposed by those workarounds are only noticed in this closed scope. For open source projects it's much worse, since those limitations are also imposed on the users of those open source projects.
It is currently even unclear, what should be used in production and what not. The new function builders feature has not even gone through Swift Evolution yet (and is still using an underline annotation - which usually defines them as being internal), but SwiftUI is very actively using it. You could argue, that the feature is currently taylored for SwiftUI, but still it's a strange inconsistency. And I wouldn't be surprised if there are bugs in SwiftUI that are actually bugs in the new function builders.
Long story short: as I mentioned a few times now, I do love the new features in Swift and the OS's. But this year's chaos is IMHO a real showstopper. It's not really helpful if you encounter bugs whilst still playing with the basics of a new feature. Like the new property wrappers not fully working with static properties, initializer with default values or even worse, the example of a Lazy
property wrapper given in the proposal not actually being lazy. I really do hope, that Apple has learned from this year's chaos and will stick to their (usually well-evolved) processes next time. Keeping secrets is fine - heck it's Apple we're talking about - but a secret is only a good surprise, if it works out in the end. Here's to next year's betas...