Skip to content

Production-ready reducer patterns and dependencies for The Composable Architecture.

License

Notifications You must be signed in to change notification settings

mehmetbaykar/swift-composable-architecture-extras

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

53 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Swift Composable Architecture Extras

Swift Platforms CI License

If you found this helpful, you can support more open source work!

Buy Me A Coffee


Production-ready reducer patterns and dependencies for The Composable Architecture.

Table of Contents

Philosophy

These are production-ready patterns extracted from real TCA applications. Each module solves a common problem with minimal API surface and maximum composability.

Installation

Add the package to your Package.swift:

dependencies: [
  .package(url: "https://github.com/mehmetbaykar/swift-composable-architecture-extras.git", from: "1.0.0")
]

Then add the product to your target:

.target(
  name: "YourTarget",
  dependencies: [
    .product(name: "ComposableArchitectureExtras", package: "swift-composable-architecture-extras")
  ]
)

Requirements

Platform Minimum Version
iOS 13.0+
macOS 10.15+
tvOS 13.0+
watchOS 6.0+
Swift 6.2+
TCA 1.23.1+

Reducer Modules

Analytics

A generic analytics reducer that handles provider integration using a declarative result builder syntax. Define events once, track everywhere.

AnalyticsReducerOf<Self, AppEvent> { state, action in
  switch action {
  case .viewAppeared: .screenViewed(name: "Home")
  case .dismissed: []
  }
}

Full documentation

Filter

A reducer modifier that conditionally executes the wrapped reducer based on state and action predicates. Perfect for feature flags, boundary enforcement, and action gating.

Reduce { state, action in
  // Business logic
}
.filter { state, action in
  state.isFeatureEnabled
}

Full documentation

FormValidation

A declarative form validation system with automatic error state management. Define validation rules once, get real-time feedback on every field change.

FormValidationReducer(
  submitAction: \.submitTapped,
  onFormValidatedAction: .loginSucceeded,
  validations: [
    FieldValidation(field: \.email, errorState: \.emailError, rules: [.nonEmpty(fieldName: "Email")])
  ]
)

Full documentation

Haptics

A universal haptics module that provides state-triggered haptic feedback across iOS, macOS, and watchOS. Trigger haptics declaratively when state changes.

Reduce { state, action in
  // Business logic
}
.haptics(.selection, triggerOnChangeOf: \.selectedIndex)
.haptics(.impactMedium(), triggerOnChangeOf: \.count, isEnabled: \.hapticsEnabled)

Full documentation

Printers

Debug printing utilities with customizable action filtering and formatted output.

Reduce { state, action in
  // Business logic
}
._printChanges(.prettyConsole(
  allowedActions: .not(.init { if case .binding = $0 { true } else { false } }),
  showTimestamp: true
))

Full documentation

ScreenAwake

Prevents device screen from auto-locking during specific app states. Works across iOS, tvOS, macOS, and watchOS with platform-appropriate implementations.

Reduce { state, action in
  // Business logic
}
.screenAwake(when: \.isPlaying)

Full documentation

ScreenBrightness

State-triggered screen brightness control for TCA applications. Automatically adjusts screen brightness based on state changes with smart restoration to original brightness.

Reduce { state, action in
  // Business logic
}
.screenBrightness(level: \.brightnessLevel)

Platform Support: iOS only. macOS, watchOS, and tvOS compile but are no-ops (no public brightness APIs exist).

Full documentation

Dependency Modules

AppInfo

A lightweight TCA dependency for accessing app bundle metadata including version strings, build numbers, and bundle identifiers.

@Dependency(\.appInfo) var appInfo

let version = appInfo.appVersion()
let build = appInfo.buildNumber()
let bundleId = appInfo.bundleIdentifier()

Full documentation

DeviceInfo

A cross-platform TCA dependency for accessing device system information: CPU usage, memory, disk storage, battery, network connectivity, thermal state, low power mode, device identity (including core counts and isiOSAppOnMac), screen info (resolution, scale, PPI, notch/Dynamic Island detection), and jailbreak detection (iOS).

@Dependency(\.deviceInfo) var deviceInfo

let identity = await deviceInfo.identity()
let cpu = await deviceInfo.cpu()
let memory = deviceInfo.memory()
let disk = deviceInfo.disk()
let thermal = deviceInfo.thermalState()
let lowPower = deviceInfo.isLowPowerModeEnabled()

#if !os(tvOS)
let battery = await deviceInfo.battery()
#endif

#if !os(watchOS)
let network = await deviceInfo.network()
#endif

#if !os(visionOS)
let screen = await deviceInfo.screen()
#endif

Platform Support: iOS, macOS, tvOS, watchOS. Battery excluded on tvOS, network excluded on watchOS. Screen excluded on visionOS. Jailbreak detection iOS only.

Full documentation

OpenSettings

A cross-platform TCA dependency for opening system settings. Platform-specific enum cases ensure consumers only see options their platform supports.

@Dependency(\.openSettings) var openSettings

await openSettings.open(.general)

Full documentation

OpenURL

A cross-platform TCA dependency for opening URLs externally or in-app via SFSafariViewController (iOS).

@Dependency(\.customOpenURL) var openURL

// Open externally (all platforms)
await openURL(URL(string: "https://example.com")!)

// Open in-app (iOS only)
#if os(iOS)
await openURL(URL(string: "https://example.com")!, prefersInApp: true)
#endif

Platform Support: iOS (external + in-app), macOS, tvOS, visionOS (external only). watchOS excluded.

Full documentation

Privacy Manifest

This package includes a PrivacyInfo.xcprivacy privacy manifest as required by Apple for third-party SDKs.

Declared API Categories

Category Reason Code Usage
Disk Space (NSPrivacyAccessedAPICategoryDiskSpace) 85F4.1 DeviceInfo module queries disk capacity via URLResourceKey to display storage information to the user
File Timestamp (NSPrivacyAccessedAPICategoryFileTimestamp) C617.1 DeviceInfo module's jailbreak detection (iOS only) uses FileManager.attributesOfItem(atPath:) which internally calls stat()

For App Developers

The privacy manifest bundled with this package covers the APIs used by the package itself. If your app uses the Analytics module with real analytics providers (Firebase, Amplitude, etc.), you must declare any applicable NSPrivacyCollectedDataTypes in your app's own privacy manifest.

Star History

Star History Chart

Contributing

Contributions are welcome! Please see CONTRIBUTING.md for guidelines.

Acknowledgments

Built on top of The Composable Architecture by Point-Free.

License

This project is licensed under the MIT License. See LICENSE for details.

About

Production-ready reducer patterns and dependencies for The Composable Architecture.

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Packages

No packages published

Contributors 2

  •  
  •  

Languages