github pointfreeco/swift-composable-architecture 0.24.0

latest releases: 1.10.4, 1.10.3, 1.10.2...
2 years ago
  • 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.

Don't miss a new swift-composable-architecture release

NewReleases is sending notifications on new releases.