Road to 1.0 #1477
Replies: 12 comments 63 replies
-
We have another change we'd like to make, but it requires more input from the community. We currently support iOS back to 13 as well as Swift 5.5+5.6. That comes with a decent amount of code complexity (we have lots of So, we'd like to drop support for iOS 13 and Swift 5.6 in the 1.0 release of TCA. Two things to keep in mind if you need to support iOS 13 or Swift 5.6:
So, is this going to be problematic for a large number of people? |
Beta Was this translation helpful? Give feedback.
-
Is there hope for native CasePaths to make it into the library in 1.0? |
Beta Was this translation helpful? Give feedback.
-
For those watching, we merged #1478 yesterday, which will hard-deprecate any instances of @tgrapperon has also done some corresponding work for the |
Beta Was this translation helpful? Give feedback.
-
We just posted a side discussion about another change we'd like to make for 1.0: Deprecating Let us know what you think! |
Beta Was this translation helpful? Give feedback.
-
Another update! We just released 0.43.0 as the first step mentioned in this post. |
Beta Was this translation helpful? Give feedback.
-
Hot take: It seems we have a unique and time-limited opportunity to be a little bolder with new APIs and experiment with a few things that were kept apart to avoid increasing the surface too much. I was for example thinking about generalized Furthermore, an hypothetical |
Beta Was this translation helpful? Give feedback.
-
How long will it roughly take to get the beta up for navigation? There some old UIKit views I currently have that I'm looking to refactor to SwiftUI but lack of navigation support is making me second guess using TCA for now (well just for that feature, still using TCA in other parts of the app) |
Beta Was this translation helpful? Give feedback.
-
Will the new navigation features be applicable to UIKit apps? |
Beta Was this translation helpful? Give feedback.
-
Has there been any consideration given to this shape of reducer as part of 1.0? func reduce(state: inout State, action: Action) async -> Action? Why not just return optional actions asynchronously rather than returning a task? Then instead of returning case .someAction:
return .task {
let result = await dependency.asyncWork()
return .otherAction(result)
} case .someAction:
let result = await dependency.asyncWork()
return .otherAction(result) I suspect it has something to do with cancellation? |
Beta Was this translation helpful? Give feedback.
-
Once 1.0 version is released. Are you guys planning on doing a video on how to use composable architecture again? I found the original video very helpful. I believe it was the 100th. Very in-depth. I think people will find this extremely useful @stephencelis @mbrandonw |
Beta Was this translation helpful? Give feedback.
-
anyone else spamming refresh seeing if there's going to be a new pinned discussion this weekend? 🤞🤠!! |
Beta Was this translation helpful? Give feedback.
-
I took my time to read all the threads and the ideas from the community and it's really amazing to see all the attention to TCA evolution. Great job to all the people making this possible! 😃 @stephencelis @mbrandonw I have a question, Do you have any plans to make TCA library platform agnostic for 1.0 or X.0 ? |
Beta Was this translation helpful? Give feedback.
-
It’s been almost 2 and a half years since we first released the Composable Architecture, so we’ve been getting more and more questions about its 0.x.x prerelease versioning, what’s holding up a 1.0, and (mostly jokingly) whether it’s “ready for production” yet 😆
We thought it’d be a good opportunity to lay out our roadmap, and detail our plans for rolling out some of the first breaking changes we’d like to introduce in preparation of the release.
What’s missing?
We’ve held off on 1.0 for this long not because we believe the library is in beta/unstable territory, but because there were a few key problem areas of library use that came up again and again, and we wanted to provide the nicest built-in solutions to them before considering the Composable Library a “complete” package.
We’ve slowly chipped away at these problem areas, which led to two significant public betas this year:
Concurrency: We wanted to make working with effects in the Composable Architecture much more approachable. Rather than require library-level use of Combine, which is powerful but comes with a significant learning curve, we introduced a friendlier set of async-await APIs.
Protocol: We finally merged this feature on Monday, and it introduces a friendlier, more modern interface for building features in the Composable Architecture.
So...what's left!?
Navigation
We think the final “missing” feature is a holistic story for navigation. Navigation is a significant part of any application, and while the Composable Architecture has shipped with demonstrations of navigation from its first release, we’ve been far from happy with them.
So we’ve been experimenting with better navigation tools from day one, and over time have made significant strides. SwiftUI 3 completely revamped its stack navigation, so we’ve done our best to digest these changes and intend to ship tools that fully embrace all of SwiftUI’s navigation idioms, and even improve upon them.
So Navigation is our next and final focus before shipping a 1.0. We still have some experimentation and polish to do, but when we’re ready we’ll have another beta period waiting for you!
Other in-flight work
We have many ongoing experiments in the Composable Architecture that we do not consider blockers for 1.0. Some of these features will make their way in before 1.0 is released. This includes work on a "non-exhaustive" version of the test store first demonstrated by @krzysztofzablocki.
Breaking changes
Throughout the 0.x.x period, we’ve done our best to maintain source compatibility across releases, and we’ve managed a large catalog of deprecations over many many releases. This means that all changes have been additive, even changes that have been complete reimaginings of existing features, like the
ReducerProtocol
. 1.0 gives us the opportunity to shed off some of these deprecated features, and tidy up the new features in the process.There are two major changes we’d like to make that will require a few releases and some churn for our users, but we hope that you all find it worth it!
Removing the old
Reducer
structThe
ReducerProtocol
is now the de facto way of building reducers in the Composable Architecture. Alongside its release, we renamed the existingReducer
struct toAnyReducer
, but provided a soft-deprecated type alias for compatibility.ReducerProtocol
is a mouthful, though, so we’d like to take steps over a few releases to fully deprecate the oldReducer
struct and finally renameReducerProtocol
toReducer
. We will accomplish this in the following releases:Very soon we plan on shipping 0.43.0 and hard-deprecating the
Reducer
type alias. This will introduce a number of warnings to projects that have not yet migrated to theReducerProtocol
. To fix these warnings, you can simply rename all instances ofReducer
toAnyReducer
, and Xcode should be able to help a lot with that.After 0.43.0, we will introduce a release candidate branch for 1.0 that will directly track the most recent release in the library with some additional, bigger breaking changes. Targeting this branch in your project will allow you to get a head start on being fully 1.0-compatible.
The changes include:
typealias Reducer = AnyReducer
ReducerProtocol
toReducer
typealias ReducerProtocol = Reducer
If you have already updated your code base to 0.43.0, then none of these changes are breaking. You will just have to rename occurrences of
ReducerProtocol
toReducer
, which Xcode should be able to help with.Closer to 1.0’s release, we will take steps to fully deprecate
AnyReducer
and its APIs.Our aim is to minimize friction, despite the above changes. So with 1.0 we do not plan on leaving folks that rely on
AnyReducer
behind. Instead, we plan on allowing folks to continue to useAnyReducer
, but we will hide this deprecated type and its APIs from view, either as a companion module that you will need to import, or by utilizing@_spi
imports to hide them from view and use unless specifically imported via@_spi(AnyReducer) import ComposableArchitecture
.Removing many Combine-specific features of
Effect
With the Concurrency release, we vastly simplified the
Effect
type, with a focus on 3 entry points for creating effects using Swift Concurrency (.run
,.task
, and.fireAndForget
). In the process, we soft-deprecated much of the type’s existing Combine integration, and before 1.0, we’d like to remove as much of this legacy integration as possible. Folks that like using Combine can continue to do so by iterating over Combine’sAsyncPublisher
async sequence in anEffect.run
.Effect
was initially designed to be used as a Combine publisher, so it picked up some quirks from Combine that feel no longer necessary. For example, it picked up aFailure
generic from thePublisher
protocol, but thisFailure
is always locked toNever
when used from within a reducer.With the new entry points designed for Swift Concurrency, the
Failure
generic no longer makes sense, so we’d like to simplifyEffect<Action, Failure>
toEffect<Action>
. We intend to do so over a number of releases, in a fashion similar to our planned rename of theReducerProtocol
:With 0.43.0, we will rename
Effect
toEffectPublisher
and provide a soft-deprecated typealias forEffect = EffectPublisher
so that existing code still compiles. We will also introduce a typealiasEffectTask<Action> = Effect<Action, Never>
, which will be the new type you should start using in your reducers. We will also update the reducer signature to useEffectTask
for simplicity.Shortly after (in 0.44.0?), we will hard-deprecate the
Effect
type alias, which means those usingEffect<Action, Never>
can just rename toEffectTask<Action>
, and those that useEffect
with a non-Never
failure can either take the opportunity to convert that code to async/await, or they can rename toEffectPublisher
.And then, we will make the following changes to the prerelease 1.0 branch so that you can get a head start on updating your codebase to be 1.0-compliant:
Effect
type aliasEffectTask
toEffect
typealias EffectTask = Effect
so that all existing uses ofEffectTask
continue to work, and Xcode should be able to help make these changes for you.Closer to 1.0’s release, we will take steps to fully deprecate
EffectPublisher
and its APIs. And similar to how we handled the removal ofAnyReducer
by using@_spi
, we will hideEffectPublisher
behind@_spi
so that it is still accessible, but just with extra work of needing to specify@_spi
when importing the Composable Architecture.We want your input!
These changes are not insignificant, but we believe they pave the way to a simpler 1.0 that will be easier to introduce to your team mates and colleagues 🙂
It’s worth mentioning that the beta period for our navigation tools will probably be comparable to what it was for the reducer protocol, and so that means the 1.0 prerelease branch will be around for quite awhile so that people should have plenty of time to update their codebases.
Please let us know if you see any issues with our strategies, or if you have any suggestions.
Beta Was this translation helpful? Give feedback.
All reactions