Extensions for TCA.
Note
The package is early beta (feel free suggest your improvements here)
Core manages underlying optional store, enables users to design UI components with lazy logical bindings. This approach allows to derive configuration logic out of initializers and treat components (primarilly UI-components) as containers that can exist without any logic.
Is a generic object driven by the core, since Swift doesn't allow inheritance from multiple classes, not every class that conforms to ComposableObjectProtocol can be downcasted to ComposableObject, good example is ComposableObject and ComposableNSObject classes, which are not interchangeable. Provides helpers for binding and scoping cores.
class ExampleObject: ComposableObjectOf<ExampleFeature> {
override func scope(_ store: Store?) {
super.scope(store)
childObject.core.setStore(store?.scope(
state: \.child.state,
action: \.child.action
))
}
override func bind(
_ store: Store,
into cancellables: Core.Cancellables
) {
super.bind(store, into: cancellables)
// This API is not yet available
store.observe(\.text)
.assign(to: self, \.text)
.store(in: cancellables)
}
}Pullbacks improve Reducers composition by replacing switch statements.
Pullback(\.path.to.child.action) { state in
return .send(.parentAction)
}
Pullback(\.path.to.child.action) { state, childAction in
return .send(.parentAction)
}
Pullback(\.path.to.children, action: \.child.action) { state, id, childAction in
return .send(.parentAction)
}Allows to track changes in derived states.
SomeReducer().onChange(of: \.localState) { state, oldValue, newValue in
return .send(.parentAction)
}Indexed ForEach is useful when working with arrays
._forEach(
\.arrayOfElements, // non-identified
action: \.pathToAction,
element: { ElementReducer() }
)Labeled ForEach is useful for multiline ergonomics
forEach(
state: \.arrayOfElements,
action: \.pathToAction,
element: { ElementReducer() }
)
._forEach(
state: \.arrayOfElements, // non-identified
action: \.pathToAction,
element: { ElementReducer() }
)Note
The product is compatible with non-Apple platforms, however it uses conditional compilation, so APIs are only available on Apple platforms
CustomCocoaView that is also ComposableObjectProtocol
public class ExampleCocoaView: ComposableCocoaViewOf<ExampleFeature> {
// Initial configuration
override public func _init() {
super._init()
}
// Action example
func onTap() {
core.store?.send(.tap)
}
// Scoping
override public func scope(_ store: Store?) {
super.scope(store)
childView.core.setStore(store?.scope(
state: \.child.state,
action: \.child.action
))
}
// Binding
override public func bind(
_ store: Store,
into cancellables: Core.Cancellables
) {
super.bind(store, into: cancellables)
// This API is not yet available
store.observe(\.text)
.assign(to: label, \.text)
.store(in: cancellables)
}
}CustomCocoaViewController that is also ComposableObjectProtocol. Composable controllers won't scope/bind values untill managed object is loaded (view for ViewControllers, window for WindowControllers). API is similar to ComposableCocoaView.
ComposableTabViewControlleris also available oniOSComposableWindowControlleris available onmacOS
Note
The product is compatible with non-Apple platforms, however it uses conditional compilation, so APIs are only available on Apple platforms
Protocol for SwiftUI views that improves composability. Composable views can only be initialized with optional stores.
public struct ExampleView: ComposableView {
@UIBindable
private var store: StoreOf<ExampleFeature>
public init(_ store: StoreOf<ExampleFeature>) {
self.store = store
}
public var body: some View { /*...*/ }
}Umbrella product that exports everything.
You can add composable-architecture-extensions to an Xcode project by adding it as a package dependency
- From the File menu, select Swift Packages › Add Package Dependency…
- Enter
"https://github.com/capturecontext/composable-architecture-extensions"into the package repository URL text field - Choose products you need to link to your project.
If you use SwiftPM for your project structure, add composable-architecture-extensions dependency to your package file.
.package(
url: "https://github.com/capturecontext/composable-architecture-extensions.git",
.upToNextMinor("0.3.0-alpha.1")
)Do not forget about target dependencies:
.product(
name: "<#Product#>",
package: "composable-architecture-extensions"
)This library is released under the MIT license. See LICENSE for details.