Releases: pointfreeco/swift-composable-architecture
0.24.0
-
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.catchToEffectoverload that takes a transform function, avoiding the need for an extramap(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 (
AlertStateandActionSheetState) 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
animationparameter, 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
#fileIDnow instead of#fileto reduce debug noise. -
Fixed:
Effect.throttleshould now clean up old values being debounced in itslatest: falsestrategy, preventing the occasional old value from emitting (thanks @p4checo). -
Fixed:
Effect.debounceshould 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.publisherdocumentation. -
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
- Added: support for concurrency-powered APIs like SwiftUI's
View.refreshable()viaViewStore.send(_:while:)andViewStore.suspend(while:), which will suspend the current task while a predicate is true. - Bug fixed:
IfLetStoreshould never re-render its initial state when its state goesnil(thanks @ollitapa). - Bug fixed:
Effect.throttleis now synchronized, eliminating potential data races (thanks @p4checo). - Infrastructure: documentation cleanup (thanks @konomae).
0.22.0
- Added:
Effect.throttlecan 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
- 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.bindingnow 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 concreteCasePathvalue, this is a breaking change, and you can pass along theCasePath.extract(from:)method, instead. - Changed:
TestStorehas relaxed itsEquatableconstraint onAction. It is only required for whenTestStore.receives actions from effects. - Performance improved: view stores now perform the minimum number of equality checks necessary (thanks @iampatbrown).
- Fixed:
ViewStore.publishernow 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
- Added:
Effect.deferred(), for delaying the execution of an effect by a given time (compare toPublisher.delay(), which delays merely the delivery of some work that has already been performed). Thanks, @wendyliga. - Updated:
SwitchStorenow supports up to 9CaseLetviews. - 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.sendand asynchronous effect received. This means synchronous effects (returned immediately from a reducer viaEffect.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: usePublisher.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
- Added: a new overload of
Reducer.pullbackfor 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
SwitchStoreview for converting stores on enum state into stores on individual enum cases (thanks @lukeredpath for sketching out the original implementation). - Changed:
Effect.timernow callscancelInFlight: trueunder 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 usingPublishers.Timerinstead before upgrading. - Fixed:
ForEachStorehas 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
- Updated:
IfLetStoreandForEachStoreclosures are now view builders. - Changed:
IfLetStore's optionalelsebranch now takes a view builder closure. The overload that takes anelseview directly has been deprecated. - Fixed: A bug in iOS 13's Combine can cause uses of the
Failpublisher to crash. We have updatedEffect.init(error:)to not useFailunder the hood and avoid this crash. - Fixed: A crash related to behavior in SwiftUI's
ForEachhas been fixed, where theIdentifiedArrayversion ofForEachStorewould 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
- Added:
Effect.failing, an effect that will cause an XCTest assertion failure if it is subscribed to. - Added: A new
ViewStoreconvenience initializer forVoidstate (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:
TextStatenow has a custom debug output format for easier debugging. - Infrastructure: various documentation improvements and fixes for TicTacToe.
0.16.0
- Changed:
Reducer.optionalreducers no longer triggerassertionFailures. Instead, by default they set a breakpoint that can be resumed inDEBUGmode. This breakpoint can be disabled with an argument.RELEASEbuilds remain unaffected. (#296) - Changed: Test Stores now collocate unfinished effect failures with the originating action that kicked each effect off. These failures were previously aggregated to the unrelated line in which
store.assertwas called. (#413) - Infrastructure: Improved documentation (thanks @Steven0351).
0.15.0
- Added: A new
ViewStore.send(_:animation:)helper for SwiftUI, which wraps an action in awithAnimationblock. - Added: TestStore steps can now group a series of steps together into a single
.sequencestep.