Skip to content

Releases: pointfreeco/swift-composable-architecture

0.25.1

24 Aug 21:24
68664c1
Compare
Choose a tag to compare
  • Fixed: a regression introduced in 0.25.0, where TestStore failures were no longer printed in a proportional diff format, has been addressed.
  • Fixed: removed a redundant conformance (thanks @aroben).
  • Infrastructure: the Composable Architecture's test suite now uses XCTAssertNoDifference instead of XCTAssertEqual.

0.25.0

23 Aug 02:50
575d7c0
Compare
Choose a tag to compare
  • Added: the Composable Architecture now uses Custom Dump for its debugging and testing tools. This library improves upon the original debugging/diffing tools that came with earlier versions of the Composable Architecture by collapsing unchanged parts of the diff, and more.
  • Added: a French translation of the README (thanks @nikitamounier).
  • Changed: ViewStore.suspend(while:) now uses Combine's async/await tools under the hood (thanks @iampatbrown for further cleanup).
  • Changed: Reducer.optional and other methods that took file and line parameters previously took them as unnamed arguments. They have been updated to take file and line as named arguments.
  • Infrastructure: refactored Tic-Tac-Toe to better model the board's domain with a nested Three data type.

0.24.0

16 Aug 13:56
96cdc7e
Compare
Choose a tag to compare
  • Added: Effect.task, for wrapping async/await work in an effect.

    Effect.task {
      guard
        case let .some((data, _)) = try? await URLSession.shared
          .data(from: .init(string: "http://numbersapi.com/42")!)
      else { return "Could not load" }
    
      return String(decoding: data, as: UTF8.self)
    }
  • Added: an Effect.catchToEffect overload that takes a transform function, avoiding the need for an extra map (thanks @eimantas).

    // before:
    return environment.apiClient.fetch()
      .catchToEffect()
      .map(MyAction.apiResponse)
    
    // after:
    return environment.apiClient.fetch()
      .catchToEffect(MyAction.apiResponse)
  • Added: Effect.cancel(ids:), which can cancel multiple effects at once by taking multiple cancel identifiers.

    return .cancel(ids: OnAppearId(), ApiRequestId())
  • Added: Alert and action sheet helpers (AlertState and ActionSheetState) can now be configured with animated button actions (thanks @fonkadelic).

    Support comes with a slightly new API and a deprecation (read: breaking change) of the old API:

    // before:
    primaryButton: .destructive(TextState("Delete"), send: .deleteButtonTapped),
    
    // after:
    primaryButton: .destructive(TextState("Delete"), action: .send(.deleteButtonTapped)),

    The newer API comes with an overloaded animation parameter, for specifying an animation for the action when sent back to the reducer:

    primaryButton: .destructive(
      TextState("Delete"),
      action: .send(.deleteButtonTapped, animation: .default)
    ),
  • Added: Alert and action sheet helpers for UIKit (thanks @andreyz).

    class MyViewController: UIViewController {
      let store: Store<MyState, MyAction>
      let viewStore: ViewStore<MyState, MyAction>
      private var cancellables: Set<AnyCancellable> = []
      private weak var alertController: UIAlertController?
      ...
      func viewDidLoad() {
        ...
        self.viewStore.publisher
          .alert
          .sink { [weak self] alert in
            guard let self = self else { return }
            if let alert = alert {
              let alertController = UIAlertController(state: alert, send: {
                self.viewStore.send(.settings($0))
              })
              self.present(alertController, animated: true, completion: nil)
              self.alertController = alertController
            } else {
              self.alertController?.dismiss(animated: true, completion: nil)
              self.alertController = nil
            }
          }
          .store(in: &cancellables)
      }
    }
  • Updated: WithViewStore.debug() now prints a diff of view state whenever its body is evaluated. This can be used to determine what change to what portion of sub-state was responsible for the evaluation.

  • Updated: code that prints file debug information uses #fileID now instead of #file to reduce debug noise.

  • Fixed: Effect.throttle should now clean up old values being debounced in its latest: false strategy, preventing the occasional old value from emitting (thanks @p4checo).

  • Fixed: Effect.debounce should now always deliver on the scheduler it is provided.

  • Fixed: A minimum deployment target of macOS 11 should now compile without error (thanks @aroben).

  • Infrastructure: Improved ViewStore.publisher documentation.

  • Infrastructure: Added an Italian translation of the README (thanks @Bellaposa).

  • Infrastructure: Added a SwiftUI case study for focus state.

  • Infrastructure: The Tic-Tac-Toe demo has been modernized. It now uses SPM for modularization instead of frameworks.

  • Infrastructure: Some cleanup and modernization of demo code.

0.23.0

26 Jul 19:27
Compare
Choose a tag to compare
  • Added: support for concurrency-powered APIs like SwiftUI's View.refreshable() via ViewStore.send(_:while:) and ViewStore.suspend(while:), which will suspend the current task while a predicate is true.
  • Bug fixed: IfLetStore should never re-render its initial state when its state goes nil (thanks @ollitapa).
  • Bug fixed: Effect.throttle is now synchronized, eliminating potential data races (thanks @p4checo).
  • Infrastructure: documentation cleanup (thanks @konomae).

0.22.0

16 Jul 19:26
a2319ff
Compare
Choose a tag to compare
  • Added: Effect.throttle can throttle how often its associated action is fed back into the reducer (thanks @kerryknight).
  • Regression fixed: A change in 0.21.0 that prevented store publishers from emitting actions if their view stores were deinitialized. This mainly affected UIKit apps.
  • Regression fixed: A change in 0.20.0 that could leave an action buffered in the store and emit late (thanks @heyltsjay).

0.21.0

12 Jul 03:10
b4f5d0e
Compare
Choose a tag to compare
  • Changed: the Composable Architecture now depends on Identified Collections for IdentifiedArray, which has been rewritten for correctness and performance. There are some breaking changes, which are documented in its release.
  • Changed: support for Swift 5.1 and 5.2 has been dropped. Please use Swift 5.3 (Xcode 12) or later, or this is of course a breaking change, and you must lock your application to swift-composable-architecture 0.20.0 or earlier.
  • Changed: Reducer.binding now takes an extract function, not a case path. Case path expressions can still be used, meaning existing uses should generally continue to compile. If you were passing a concrete CasePath value, this is a breaking change, and you can pass along the CasePath.extract(from:) method, instead.
  • Changed: TestStore has relaxed its Equatable constraint on Action. It is only required for when TestStore.receives actions from effects.
  • Performance improved: view stores now perform the minimum number of equality checks necessary (thanks @iampatbrown).
  • Fixed: ViewStore.publisher now emits the current store state, and not the previous state (thanks @maximkrouk, @iampatbrown).
  • Infrastructure: cleaned up recursive case study, web socket case study; added benchmarking target.

0.20.0

28 Jun 11:58
3ca8249
Compare
Choose a tag to compare
  • Added: Effect.deferred(), for delaying the execution of an effect by a given time (compare to Publisher.delay(), which delays merely the delivery of some work that has already been performed). Thanks, @wendyliga.
  • Updated: SwitchStore now supports up to 9 CaseLet views.
  • Performance improvement/fix: the number of times Store.scope's state transform function has been minimized. Previously it was evaluated an extra time, multiplied by downstream scopes.
  • Performance improvement/fix: the number of times ViewStore's duplicate check has been reduced.
  • Performance improvement/fix: a store publisher will only emit a single state change per synchronous Store.send and asynchronous effect received. This means synchronous effects (returned immediately from a reducer via Effect.init(value:)) will no longer result in extra publisher emissions. This is a breaking change if your application previously depended on each of these emissions. Workaround: use Publisher.receive(on:) to schedule these effects on the next run loop tick.
  • Infrastructure: cleaned up demo apps and documentation; added an Indonesian translation of the README (thanks @wendyliga).

0.19.0

14 Jun 14:57
Compare
Choose a tag to compare
  • Added: a new overload of Reducer.pullback for working with enum-based state. It uses a case path instead of a writable key path for extracting and embedding state for a particular enum case.
  • Added: a new SwitchStore view for converting stores on enum state into stores on individual enum cases (thanks @lukeredpath for sketching out the original implementation).
  • Changed: Effect.timer now calls cancelInFlight: true under the hood to automatically cancel any in-flight timers with the same cancellable id (thanks @dannyhertz). If you rely on the existing behavior, which allows for timers to interleave and stack on one another, this is a breaking change and you must manually create your timers using Publishers.Timer instead before upgrading.
  • Fixed: ForEachStore has been optimized and a crash related to removing rows has been fixed.
  • Fixed: documentation cleanup.
  • Infrastructure: modernized example/demo code, along with assorted fixes (thanks @yimajo, @filblue).

0.18.0

20 Apr 17:08
0f026d3
Compare
Choose a tag to compare
  • Updated: IfLetStore and ForEachStore closures are now view builders.
  • Changed: IfLetStore's optional else branch now takes a view builder closure. The overload that takes an else view directly has been deprecated.
  • Fixed: A bug in iOS 13's Combine can cause uses of the Fail publisher to crash. We have updated Effect.init(error:) to not use Fail under the hood and avoid this crash.
  • Fixed: A crash related to behavior in SwiftUI's ForEach has been fixed, where the IdentifiedArray version of ForEachStore would unsafely unwrap elements after removal.
  • Improved: documentation for Store.ifLet (thanks @mluisbrown).
  • Infrastructure: improve UIKit demo support of dark mode (thanks @hungtruong).

0.17.0

22 Mar 18:01
84b9a00
Compare
Choose a tag to compare
  • Added: Effect.failing, an effect that will cause an XCTest assertion failure if it is subscribed to.
  • Added: A new ViewStore convenience initializer for Void state (thanks @siejkowski).
  • Changed: The fireAndForget() method is now more permissive. It will now ignore all output and failure for you before upcasting the output and failure types to any type.
  • Changed: TextState now has a custom debug output format for easier debugging.
  • Infrastructure: various documentation improvements and fixes for TicTacToe.