Skip to content

Pull request#2

Open
Gleb-Kovalenko wants to merge 256 commits into
Incetro:feature/fork_pointfreefrom
pointfreeco:main
Open

Pull request#2
Gleb-Kovalenko wants to merge 256 commits into
Incetro:feature/fork_pointfreefrom
pointfreeco:main

Conversation

@Gleb-Kovalenko
Copy link
Copy Markdown

No description provided.

stephencelis and others added 30 commits August 26, 2024 10:14
2.1.0 restores the ability for TCA AppKit apps to access the `observe`
function.
* Allow an alert to present another alert

When we added support for vanilla SwiftUI modifiers, we lost the ability
to present one alert after another because `nil` writes to the alert
bindings unconditionally dismissed the feature, even if the feature was
freshly presented.

This fixes things by suppressing dismissal when the identity of a
presented item has changed.

Fix #3272.

* wip
* `@preconcurrency @MainActor` isolation of `Store`

* Remove unneeded `@MainActor`s

* Remove thread checking code

* Remove unneeded `@MainActor`s

* Swift 5.10 compatibility fixes

* wip

* More 5.10 fixes

* wip

* fixes

* wip

* wip

* up the timeout

* wip

* Fixes

* Remove mainActorASAP in favor of mainActorNow. (#3288)

* wip

* Run swift-format

* Update README.md

* Fix integration tests. (#3294)

* Fix integration tests.

* wip

* wip

* Run swift-format

* mainActorNow doesnt need escaping closure

* wip

* migration guide

* wip

* Update MigratingTo1.14.md

---------

Co-authored-by: Brandon Williams <mbrandonw@hey.com>
Co-authored-by: Brandon Williams <135203+mbrandonw@users.noreply.github.com>
Co-authored-by: mbrandonw <mbrandonw@users.noreply.github.com>
* `@preconcurrency @MainActor` isolation of `Store`

* Remove unneeded `@MainActor`s

* Remove thread checking code

* Remove unneeded `@MainActor`s

* Swift 5.10 compatibility fixes

* wip

* More 5.10 fixes

* wip

* fixes

* wip

* wip

* up the timeout

* wip

* Fixes

* wip

* wip

* wip

* wip

* wip

* wip

* Main actor logger

* wip

* wip

* wip

* fix

* fix

* fix

* fix compilation error

* wip

* wip

* bring back yield

---------

Co-authored-by: Brandon Williams <mbrandonw@hey.com>
Now that we've locked to Swift Navigation >=2.2, we get this method for free.
* fix Typo

* delete deprecated content
* `@preconcurrency @MainActor` isolation of `Store`

* Remove unneeded `@MainActor`s

* Remove thread checking code

* Remove unneeded `@MainActor`s

* Swift 5.10 compatibility fixes

* wip

* More 5.10 fixes

* wip

* fixes

* wip

* wip

* up the timeout

* wip

* Fixes

* wip

* wip

* wip

* wip

* wip

* Fix binding action sendability

* Address more binding action sendability

* more bindable action sendability

* more bindable action warnings

* fix

---------

Co-authored-by: Brandon Williams <mbrandonw@hey.com>
* Require sendable IDs in cancellation/reducers

Many of our APIs warn that we are passing hashable identifiers across
concurrency boundaries, so we should require that they're sendable.

* fix

* fix

* Fix
* `@preconcurrency @MainActor` isolation of `Store`

* Remove unneeded `@MainActor`s

* Remove thread checking code

* Remove unneeded `@MainActor`s

* Swift 5.10 compatibility fixes

* wip

* More 5.10 fixes

* wip

* fixes

* wip

* wip

* up the timeout

* wip

* Fixes

* wip

* wip

* wip

* wip

* wip

* Fix binding action sendability

* Address more binding action sendability

* more bindable action sendability

* more bindable action warnings

* fix

* Make `Effect.map` sendable

* Make `Effect.actions` sendable

Also moves it to the test target, since it's only really used there.

* Make `AnyPublisher.create` sendable

* Make `_SynthesizedConformance` sendable

* Avoid non-sendable captures of `self` in reducers

We can capture the sendable case path instead.

* Make `ViewStore.yield` sendable

* Address internal sendability warning

* fix

* Another small warning

---------

Co-authored-by: Brandon Williams <mbrandonw@hey.com>
* Address effect cancellation sendability

* fix

* wip

* wip
* Address `Reducer._printChanges()` sendability

Because printing is done on a queue, both `State` and `Action` must be
sendable. While `State` is easy enough to make sendable, it might be a
pain to do so in a large, modularized application. Actions are not
always so easy, but are in simple cases.

Alternately, since this is a debugging affordance:

1. We could forego sendability since all we're doing is hitting it with
   a `Mirror` at the end of the day, and traffic the state/action along
   in a `nonisolated(unsafe)`.

2. We could ditch the queue...but that could affect the performance
   pretty negatively in some cases.

* Unchecked send the debug printing
* Require main actor isolation in store collection

* `preconditionIsolated` is not available in iOS <14

* Update Sources/ComposableArchitecture/Observation/IdentifiedArray+Observation.swift
…rray (#3346)

* Added failing test to document behavior with observation and identified array.

* Update Tests/ComposableArchitectureTests/ObservableTests.swift

---------

Co-authored-by: Stephen Celis <stephen@stephencelis.com>
* Update 05-HigherOrderReducers CaseStudies

* Replace alert(store:) to alert(_:)

* View clean up.

* Fixed alert.

* Update DownloadComponent.swift

---------

Co-authored-by: Brandon Williams <mbrandonw@hey.com>
Co-authored-by: Stephen Celis <stephen.celis@gmail.com>
* Warn if bindable store binding action isn't processed

Looks like the warnings we emit when we detect `BindingReducer` is
missing are only applied to view stores, and were not ported over to the
newer observable store bindings.

This PR fixes that, though the main caveat is the messages can't seem to
point to any good context. These bindings are derived from dynamic
member lookup, which can't include source context like file/line.

* wip

* Add test
#3327)

* Edit 04-Navigation-Lists-NavigateAndLoad file in SwiftUI CaseStudies

* Update Examples/CaseStudies/SwiftUICaseStudies/04-Navigation-Lists-NavigateAndLoad.swift

Co-authored-by: Stephen Celis <stephen.celis@gmail.com>

* change selection Type to `Identified<Row.ID, Counter.State?>?`

---------

Co-authored-by: Stephen Celis <stephen.celis@gmail.com>
Co-authored-by: Stephen Celis <stephen@stephencelis.com>
stephencelis and others added 30 commits March 13, 2026 09:40
* Trait-deprecate `Effect` for `EffectOf`.

The shape of `Effect` is changing in 2.0 to be `Effect<State, Action>`,
so to get ahead of the curve we are offering a trait to help folks
migrate to `EffectOf<Feature>` (supported today) when explicitly
referring to `Effect`.

* wip

* wip

* Added: Streamlined `onChange` operator

While the current version seems flexible its semantics are a little
strange: it creates a reducer and throws it away on change. This is even
incompatible with how 2.0 will do things, where mount/dismount events
rapidly triggering would make reasoning about these reducers difficult.

So instead let's prepare folks for 2.0 with a version that is more
compatible, and really just streamlines things today. It is
trait-deprecated so folks looking to migrate to 2.0 can opt-in and make
changes as necessary.

* Hard-deprecate `Store.withState`

Missed this one with all the other `@ObservableState`-specific
deprecations.

Let's not worry about trait-based deprecation here. It should be a
relatively unused API.

* Trait-deprecate `StorePublisher`

All other Combine interfaces have been hard-deprecated, for the most
part, but it is possible that this change is viral (_e.g._ in a UIKit
app), so I'm hiding it behind a trait for now.

* Trait-deprecate `Effect.merge`, `Effect.concatenate`, `Effect.map`

Since Swift concurrency landed, with `async`-`await` and task groups, we
have pushed folks towards using these tools in a `.run` effect instead
of `.merge` and `.concatenate`. While many still reach for these tools
today, Composable Architecture 2.0 is making some fundamental changes to
effects that make them more efficient and powerful but less
transformable. To prepare folks, we should deprecate them behind our 2.0
trait.

* Don't deprecate `merge`

* Update Package.swift
* Trait-deprecate `Effect` for `EffectOf`.

The shape of `Effect` is changing in 2.0 to be `Effect<State, Action>`,
so to get ahead of the curve we are offering a trait to help folks
migrate to `EffectOf<Feature>` (supported today) when explicitly
referring to `Effect`.

* wip

* wip

* Added: Streamlined `onChange` operator

While the current version seems flexible its semantics are a little
strange: it creates a reducer and throws it away on change. This is even
incompatible with how 2.0 will do things, where mount/dismount events
rapidly triggering would make reasoning about these reducers difficult.

So instead let's prepare folks for 2.0 with a version that is more
compatible, and really just streamlines things today. It is
trait-deprecated so folks looking to migrate to 2.0 can opt-in and make
changes as necessary.

* Hard-deprecate `Store.withState`

Missed this one with all the other `@ObservableState`-specific
deprecations.

Let's not worry about trait-based deprecation here. It should be a
relatively unused API.

* Trait-deprecate `StorePublisher`

All other Combine interfaces have been hard-deprecated, for the most
part, but it is possible that this change is viral (_e.g._ in a UIKit
app), so I'm hiding it behind a trait for now.

* Trait-deprecate `Effect.merge`, `Effect.concatenate`, `Effect.map`

Since Swift concurrency landed, with `async`-`await` and task groups, we
have pushed folks towards using these tools in a `.run` effect instead
of `.merge` and `.concatenate`. While many still reach for these tools
today, Composable Architecture 2.0 is making some fundamental changes to
effects that make them more efficient and powerful but less
transformable. To prepare folks, we should deprecate them behind our 2.0
trait.

* Don't deprecate `merge`

* Hard-deprecate `BindingViewState`/`BindingViewStore`

Both of these concepts were technically obsoleted by 1.7.

* wip

* wip
* Trait-deprecate `Effect` for `EffectOf`.

The shape of `Effect` is changing in 2.0 to be `Effect<State, Action>`,
so to get ahead of the curve we are offering a trait to help folks
migrate to `EffectOf<Feature>` (supported today) when explicitly
referring to `Effect`.

* wip

* wip

* Added: Streamlined `onChange` operator

While the current version seems flexible its semantics are a little
strange: it creates a reducer and throws it away on change. This is even
incompatible with how 2.0 will do things, where mount/dismount events
rapidly triggering would make reasoning about these reducers difficult.

So instead let's prepare folks for 2.0 with a version that is more
compatible, and really just streamlines things today. It is
trait-deprecated so folks looking to migrate to 2.0 can opt-in and make
changes as necessary.

* Hard-deprecate `Store.withState`

Missed this one with all the other `@ObservableState`-specific
deprecations.

Let's not worry about trait-based deprecation here. It should be a
relatively unused API.

* Trait-deprecate `StorePublisher`

All other Combine interfaces have been hard-deprecated, for the most
part, but it is possible that this change is viral (_e.g._ in a UIKit
app), so I'm hiding it behind a trait for now.

* Trait-deprecate `Effect.merge`, `Effect.concatenate`, `Effect.map`

Since Swift concurrency landed, with `async`-`await` and task groups, we
have pushed folks towards using these tools in a `.run` effect instead
of `.merge` and `.concatenate`. While many still reach for these tools
today, Composable Architecture 2.0 is making some fundamental changes to
effects that make them more efficient and powerful but less
transformable. To prepare folks, we should deprecate them behind our 2.0
trait.

* Don't deprecate `merge`

* Hard-deprecate `BindingViewState`/`BindingViewStore`

Both of these concepts were technically obsoleted by 1.7.

* Trait-deprecate `$store.scope(state: \.destination)`

The key paths must align in 2.0, so for the migration to work it must be
of the form `$store.scope(state: \.$destination)`.
* Trait-deprecate `Effect` for `EffectOf`.

The shape of `Effect` is changing in 2.0 to be `Effect<State, Action>`,
so to get ahead of the curve we are offering a trait to help folks
migrate to `EffectOf<Feature>` (supported today) when explicitly
referring to `Effect`.

* wip

* wip

* Added: Streamlined `onChange` operator

While the current version seems flexible its semantics are a little
strange: it creates a reducer and throws it away on change. This is even
incompatible with how 2.0 will do things, where mount/dismount events
rapidly triggering would make reasoning about these reducers difficult.

So instead let's prepare folks for 2.0 with a version that is more
compatible, and really just streamlines things today. It is
trait-deprecated so folks looking to migrate to 2.0 can opt-in and make
changes as necessary.

* Hard-deprecate `Store.withState`

Missed this one with all the other `@ObservableState`-specific
deprecations.

Let's not worry about trait-based deprecation here. It should be a
relatively unused API.

* Trait-deprecate `StorePublisher`

All other Combine interfaces have been hard-deprecated, for the most
part, but it is possible that this change is viral (_e.g._ in a UIKit
app), so I'm hiding it behind a trait for now.

* Trait-deprecate `Effect.merge`, `Effect.concatenate`, `Effect.map`

Since Swift concurrency landed, with `async`-`await` and task groups, we
have pushed folks towards using these tools in a `.run` effect instead
of `.merge` and `.concatenate`. While many still reach for these tools
today, Composable Architecture 2.0 is making some fundamental changes to
effects that make them more efficient and powerful but less
transformable. To prepare folks, we should deprecate them behind our 2.0
trait.

* Don't deprecate `merge`

* Hard-deprecate `BindingViewState`/`BindingViewStore`

Both of these concepts were technically obsoleted by 1.7.

* Trait-deprecate `$store.scope(state: \.destination)`

The key paths must align in 2.0, so for the migration to work it must be
of the form `$store.scope(state: \.$destination)`.

* TCA2 backport: enum scopes

TCA2 is stricter about scoping along feature boundaries, which means
composed scoping like `\.destination?.sheet` aren't desirable.

But these APIs could be improved to begin with, and have in TCA2, so
let's backport them to make the migration easier.

```swift
// Before:
$store.scope(state: \.$destination?.sheet, action: \.destination.sheet)

// After:
$store.scope(state: \.$destination, action: \.destination).sheet
```
* 1.25 Migration Guide

* wip
Updated sharedHelper function signature for Effect transition.
While this compiles in Swift 6.3, it fails in Swift 6.2. This regression
was introduced in #3858.
That way these APIs still surface as deprecated more visibly.
* Fix stack overflow related to new enum scopes

Enum scopes are a new scoping overload introduced in #3882 to prepare
folks for Composable Architecture 2.0. There was unfortunately a
recursive call that the compiler didn't catch. This should fix it.

* wip

* wip

* wip

* wip
We've found a migration path that can preserve `Effect` as it exists
today, so let's make the pre-migration less annoying.

`EffectOf` will work fine for folks who have already migrated in
preparation.
Enum scoping does not currently have a hard trait deprecation associated
with it because overloads could cause existing apps to fail to compile
with the dreaded "complex expression" error.

Users should still have a migration path here, which is served by a
trait that can be enabled temporarily.
When using @Reducer on a public or package enum, the generated computed
properties inside AllCasePaths were missing the access modifier, defaulting
to internal. This made the enum scope API inaccessible across module
boundaries.

Fixes #3893
We'll favor wrapping with `withAnimation` in TCA2.
Alerts and confirmation dialogs held in `@Reducer enum`s will require a
bit of extra ceremony to be 2.0-compatible, but 2.0 will come with more
flexible tooling around handling prompts.
…n raises deprecation warning (#3906)

In a `View` context, reading a `@Shared` value from the store's state will raise a deprecation warning when the store's `Action` conforms to `BindableAction`.

```swift
@Reducer
struct Feature {
  @ObservableState
  struct State: Equatable {
    @shared(.inMemory("value")) var value: Int = 0
  }
  enum Action: BindableAction {
    case binding(BindingAction<State>)
  }
}

struct FeatureView: View {
  let store: StoreOf<Feature>

  var body: some View {
    let _ = store.value
    // 🛑 Setter for 'value' is deprecated: Use '$shared.withLock' to modify a shared value with exclusive access; when constructing a SwiftUI binding, use 'Binding($shared)'
  }
}
```

This is because the dynamicMemberLookup selects an overload that requires a `WritableKeyPath` which is enough to trigger Swift to require a setter for the property which is invalid for a `@Shared` value. Applying `@_disfavoredOverload` will drive the lookup toward an overload requiring a `KeyPath` instead.

Co-authored-by: Sean <sean@snowfort.software>
Fixes a compiler error by helping it disambiguate between this implementation of ~= and the more constrained one declared in Binding+Observation.swift
* Fix enum scoping to alerts

* wip
* Add `scope(_:action:)` and `Scope(_:action:)`

To prepare for changes coming in 2.0, we are introducing new scoping overloads that omit the
`state:` parameter label. This label is already omitted for some scoping operations (`ifLet`,
`forEach`, etc.) and is just added noise for the dominant part of the operation.

The old API has been trait-deprecated so that folks can migrate at their own pace without too much
noise.

* wip
* Update docs for Store.

* wip
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.