├── .editorconfig
├── .github
├── CODE_OF_CONDUCT.md
├── ISSUE_TEMPLATE
│ ├── bug_report.yml
│ └── config.yml
├── package.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ ├── IDEWorkspaceChecks.plist
│ │ ├── swiftpm
│ │ └── Package.resolved
│ │ └── xcschemes
│ │ ├── ComposableArchitecture.xcscheme
│ │ └── swift-composable-architecture-benchmark.xcscheme
└── workflows
│ ├── ci.yml
│ ├── documentation.yml
│ ├── format.yml
│ └── release.yml
├── .gitignore
├── .spi.yml
├── Benchmarks
├── Benchmarks
│ └── swift-composable-architecture-benchmark
│ │ └── Benchmarks.swift
├── Package.resolved
└── Package.swift
├── ComposableArchitecture.xcworkspace
├── contents.xcworkspacedata
└── xcshareddata
│ ├── IDEWorkspaceChecks.plist
│ ├── WorkspaceSettings.xcsettings
│ ├── swiftpm
│ └── Package.resolved
│ └── xcschemes
│ ├── ComposableArchitecture.xcscheme
│ └── swift-composable-architecture-benchmark.xcscheme
├── Examples
├── .swiftpm
│ └── xcode
│ │ └── package.xcworkspace
│ │ └── contents.xcworkspacedata
├── CaseStudies
│ ├── CaseStudies.xcodeproj
│ │ ├── project.pbxproj
│ │ ├── project.xcworkspace
│ │ │ ├── contents.xcworkspacedata
│ │ │ └── xcshareddata
│ │ │ │ └── IDEWorkspaceChecks.plist
│ │ └── xcshareddata
│ │ │ └── xcschemes
│ │ │ ├── CaseStudies (SwiftUI).xcscheme
│ │ │ ├── CaseStudies (UIKit).xcscheme
│ │ │ └── tvOSCaseStudies.xcscheme
│ ├── README.md
│ ├── SwiftUICaseStudies
│ │ ├── 00-RootView.swift
│ │ ├── 01-GettingStarted-AlertsAndConfirmationDialogs.swift
│ │ ├── 01-GettingStarted-Animations.swift
│ │ ├── 01-GettingStarted-Bindings-Basics.swift
│ │ ├── 01-GettingStarted-Bindings-Forms.swift
│ │ ├── 01-GettingStarted-Composition-TwoCounters.swift
│ │ ├── 01-GettingStarted-Counter.swift
│ │ ├── 01-GettingStarted-FocusState.swift
│ │ ├── 01-GettingStarted-OptionalState.swift
│ │ ├── 02-Effects-SystemEnvironment.swift
│ │ ├── 02-SharedState-FileStorage.swift
│ │ ├── 02-SharedState-InMemory.swift
│ │ ├── 02-SharedState-Onboarding.swift
│ │ ├── 02-SharedState-UserDefaults.swift
│ │ ├── 03-Effects-Basics.swift
│ │ ├── 03-Effects-Cancellation.swift
│ │ ├── 03-Effects-LongLiving.swift
│ │ ├── 03-Effects-Refreshable.swift
│ │ ├── 03-Effects-Timers.swift
│ │ ├── 03-Effects-WebSocket.swift
│ │ ├── 04-Navigation-Lists-NavigateAndLoad.swift
│ │ ├── 04-Navigation-Multiple-Destinations.swift
│ │ ├── 04-Navigation-NavigateAndLoad.swift
│ │ ├── 04-Navigation-Sheet-LoadThenPresent.swift
│ │ ├── 04-Navigation-Sheet-PresentAndLoad.swift
│ │ ├── 04-NavigationStack.swift
│ │ ├── 05-HigherOrderReducers-Recursion.swift
│ │ ├── 05-HigherOrderReducers-ResuableOfflineDownloads
│ │ │ ├── DownloadClient.swift
│ │ │ ├── DownloadComponent.swift
│ │ │ └── ReusableComponents-Download.swift
│ │ ├── 05-HigherOrderReducers-ReusableFavoriting.swift
│ │ ├── Assets.xcassets
│ │ │ ├── AppIcon.appiconset
│ │ │ │ ├── AppIcon-60@2x.png
│ │ │ │ ├── AppIcon-76@2x.png
│ │ │ │ ├── AppIcon-iPadPro@2x.png
│ │ │ │ ├── AppIcon.png
│ │ │ │ ├── Contents.json
│ │ │ │ └── transparent.png
│ │ │ └── Contents.json
│ │ ├── CaseStudiesApp.swift
│ │ ├── FactClient.swift
│ │ ├── Info.plist
│ │ └── Internal
│ │ │ ├── AboutView.swift
│ │ │ ├── CircularProgressView.swift
│ │ │ ├── ResignFirstResponder.swift
│ │ │ ├── TemplateText.swift
│ │ │ └── UIViewRepresented.swift
│ ├── SwiftUICaseStudiesTests
│ │ ├── 01-GettingStarted-AlertsAndConfirmationDialogsTests.swift
│ │ ├── 01-GettingStarted-AnimationsTests.swift
│ │ ├── 01-GettingStarted-BindingBasicsTests.swift
│ │ ├── 02-GettingStarted-SharedStateFileStorageTests.swift
│ │ ├── 02-GettingStarted-SharedStateInMemoryTests.swift
│ │ ├── 02-GettingStarted-SharedStateUserDefaultsTests.swift
│ │ ├── 03-Effects-BasicsTests.swift
│ │ ├── 03-Effects-CancellationTests.swift
│ │ ├── 03-Effects-LongLivingTests.swift
│ │ ├── 03-Effects-RefreshableTests.swift
│ │ ├── 03-Effects-TimersTests.swift
│ │ ├── 03-Effects-WebSocketTests.swift
│ │ ├── 05-HigherOrderReducers-RecursionTests.swift
│ │ ├── 05-HigherOrderReducers-ReusableFavoritingTests.swift
│ │ └── 05-HigherOrderReducers-ReusableOfflineDownloadsTests.swift
│ ├── UIKitCaseStudies
│ │ ├── Assets.xcassets
│ │ │ ├── AppIcon.appiconset
│ │ │ │ ├── AppIcon-60@2x.png
│ │ │ │ ├── AppIcon-76@2x.png
│ │ │ │ ├── AppIcon-iPadPro@2x.png
│ │ │ │ ├── AppIcon.png
│ │ │ │ ├── Contents.json
│ │ │ │ └── transparent.png
│ │ │ └── Contents.json
│ │ ├── Base.lproj
│ │ │ └── LaunchScreen.storyboard
│ │ ├── CounterViewController.swift
│ │ ├── Info.plist
│ │ ├── Internal
│ │ │ ├── ActivityIndicatorViewController.swift
│ │ │ └── IfLetStoreController.swift
│ │ ├── ListsOfState.swift
│ │ ├── LoadThenNavigate.swift
│ │ ├── NavigateAndLoad.swift
│ │ ├── Preview Content
│ │ │ └── Preview Assets.xcassets
│ │ │ │ └── Contents.json
│ │ ├── RootViewController.swift
│ │ └── SceneDelegate.swift
│ ├── UIKitCaseStudiesTests
│ │ ├── Info.plist
│ │ └── UIKitCaseStudiesTests.swift
│ ├── tvOSCaseStudies
│ │ ├── AppDelegate.swift
│ │ ├── Assets.xcassets
│ │ │ ├── AppIcon.appiconset
│ │ │ │ ├── AppIcon.png
│ │ │ │ └── Contents.json
│ │ │ └── Contents.json
│ │ ├── Core.swift
│ │ ├── FocusView.swift
│ │ ├── Info.plist
│ │ └── RootView.swift
│ └── tvOSCaseStudiesTests
│ │ └── FocusTests.swift
├── Integration
│ ├── Integration.xcodeproj
│ │ ├── project.pbxproj
│ │ ├── project.xcworkspace
│ │ │ ├── contents.xcworkspacedata
│ │ │ └── xcshareddata
│ │ │ │ ├── IDEWorkspaceChecks.plist
│ │ │ │ └── swiftpm
│ │ │ │ └── Package.resolved
│ │ └── xcshareddata
│ │ │ └── xcschemes
│ │ │ └── Integration.xcscheme
│ ├── Integration
│ │ ├── Assets.xcassets
│ │ │ ├── AccentColor.colorset
│ │ │ │ └── Contents.json
│ │ │ ├── AppIcon.appiconset
│ │ │ │ └── Contents.json
│ │ │ └── Contents.json
│ │ ├── Info.plist
│ │ ├── IntegrationApp.swift
│ │ ├── Legacy
│ │ │ ├── BindingLocalTestCase.swift
│ │ │ ├── BindingsAnimationsTestBench.swift
│ │ │ ├── EscapedWithViewStoreTestCase.swift
│ │ │ ├── ForEachBindingTestCase.swift
│ │ │ ├── IfLetStoreTestCase.swift
│ │ │ ├── LegacyPresentationTestCase.swift
│ │ │ ├── NavigationStackTestCase.swift
│ │ │ ├── PresentationItemTestCase.swift
│ │ │ └── SwitchStoreTestCase.swift
│ │ ├── Preview Content
│ │ │ └── Preview Assets.xcassets
│ │ │ │ └── Contents.json
│ │ ├── Test Cases
│ │ │ └── MultipleAlertsTestCase.swift
│ │ ├── iOS 16+17
│ │ │ ├── NewContainsOldTestCase.swift
│ │ │ ├── NewOldSiblingsTestCase.swift
│ │ │ ├── NewPresentsOldTestCase.swift
│ │ │ ├── OldContainsNewTestCase.swift
│ │ │ └── OldPresentsNewTestCase.swift
│ │ ├── iOS 16
│ │ │ ├── BasicsTestCase.swift
│ │ │ ├── EnumTestCase.swift
│ │ │ ├── IdentifiedListTestCase.swift
│ │ │ ├── NavigationTestCase.swift
│ │ │ ├── OptionalTestCase.swift
│ │ │ ├── PresentationTestCase.swift
│ │ │ └── SiblingTestCase.swift
│ │ └── iOS 17
│ │ │ ├── ObservableBasicsTestCase.swift
│ │ │ ├── ObservableBindingLocalTest.swift
│ │ │ ├── ObservableEnumTestCase.swift
│ │ │ ├── ObservableIdentifiedListTestCase.swift
│ │ │ ├── ObservableNavigationTestCase.swift
│ │ │ ├── ObservableOptionalTestCase.swift
│ │ │ ├── ObservablePresentationTestCase.swift
│ │ │ ├── ObservableSharedStateTestCase.swift
│ │ │ └── ObservableSiblingTestCase.swift
│ ├── IntegrationUITests
│ │ ├── EnumTests.swift
│ │ ├── Internal
│ │ │ ├── BaseIntegrationTests.swift
│ │ │ └── TestHelpers.swift
│ │ ├── Legacy
│ │ │ ├── BindingLocalTests.swift
│ │ │ ├── EscapedWithViewStoreTests.swift
│ │ │ ├── ForEachBindingTests.swift
│ │ │ ├── IfLetStoreTests.swift
│ │ │ ├── LegacyNavigationTests.swift
│ │ │ ├── LegacyPresentationTests.swift
│ │ │ └── SwitchStoreTests.swift
│ │ ├── Test Cases
│ │ │ └── MultipleAlertsTests.swift
│ │ ├── iOS 16+17
│ │ │ ├── NewContainsOldTests.swift
│ │ │ ├── NewOldSiblingsTests.swift
│ │ │ ├── NewPresentsOldTests.swift
│ │ │ ├── OldContainsNewTests.swift
│ │ │ └── OldPresentsNewTests.swift
│ │ ├── iOS 16
│ │ │ ├── BasicsTests.swift
│ │ │ ├── EnumTests.swift
│ │ │ ├── IdentifiedListTests.swift
│ │ │ ├── NavigationTests.swift
│ │ │ ├── OptionalTests.swift
│ │ │ ├── PresentationTests.swift
│ │ │ └── SiblingTests.swift
│ │ └── iOS 17
│ │ │ ├── ObservableBasicsTests.swift
│ │ │ ├── ObservableBindingLocalTests.swift
│ │ │ ├── ObservableEnumTests.swift
│ │ │ ├── ObservableIdentifiedListTests.swift
│ │ │ ├── ObservableNavigationTests.swift
│ │ │ ├── ObservableOptionalTests.swift
│ │ │ ├── ObservablePresentationTests.swift
│ │ │ ├── ObservableSharedStateTests.swift
│ │ │ └── ObservableSiblingTests.swift
│ └── TestCases
│ │ └── TestCase.swift
├── Package.swift
├── README.md
├── Search
│ ├── README.md
│ ├── Search.xcodeproj
│ │ ├── project.pbxproj
│ │ ├── project.xcworkspace
│ │ │ ├── contents.xcworkspacedata
│ │ │ └── xcshareddata
│ │ │ │ └── IDEWorkspaceChecks.plist
│ │ └── xcshareddata
│ │ │ └── xcschemes
│ │ │ └── Search.xcscheme
│ ├── Search
│ │ ├── Assets.xcassets
│ │ │ ├── AppIcon.appiconset
│ │ │ │ ├── AppIcon-60@2x.png
│ │ │ │ ├── AppIcon-76@2x.png
│ │ │ │ ├── AppIcon-iPadPro@2x.png
│ │ │ │ ├── AppIcon.png
│ │ │ │ ├── Contents.json
│ │ │ │ └── transparent.png
│ │ │ └── Contents.json
│ │ ├── SearchApp.swift
│ │ ├── SearchView.swift
│ │ └── WeatherClient.swift
│ └── SearchTests
│ │ └── SearchTests.swift
├── SpeechRecognition
│ ├── README.md
│ ├── SpeechRecognition.xcodeproj
│ │ ├── project.pbxproj
│ │ └── xcshareddata
│ │ │ └── xcschemes
│ │ │ └── SpeechRecognition.xcscheme
│ ├── SpeechRecognition
│ │ ├── Assets.xcassets
│ │ │ ├── AppIcon.appiconset
│ │ │ │ ├── AppIcon-60@2x.png
│ │ │ │ ├── AppIcon-76@2x.png
│ │ │ │ ├── AppIcon-iPadPro@2x.png
│ │ │ │ ├── AppIcon.png
│ │ │ │ ├── Contents.json
│ │ │ │ └── transparent.png
│ │ │ └── Contents.json
│ │ ├── Info.plist
│ │ ├── SpeechClient
│ │ │ ├── Client.swift
│ │ │ ├── Live.swift
│ │ │ └── Models.swift
│ │ ├── SpeechRecognition.swift
│ │ └── SpeechRecognitionApp.swift
│ └── SpeechRecognitionTests
│ │ └── SpeechRecognitionTests.swift
├── SyncUps
│ ├── README.md
│ ├── SyncUps.xcodeproj
│ │ ├── project.pbxproj
│ │ └── xcshareddata
│ │ │ └── xcschemes
│ │ │ └── SyncUps.xcscheme
│ ├── SyncUps.xctestplan
│ ├── SyncUps
│ │ ├── App.swift
│ │ ├── AppFeature.swift
│ │ ├── Assets.xcassets
│ │ │ ├── AccentColor.colorset
│ │ │ │ └── Contents.json
│ │ │ ├── AppIcon.appiconset
│ │ │ │ └── Contents.json
│ │ │ ├── Contents.json
│ │ │ └── Themes
│ │ │ │ ├── Contents.json
│ │ │ │ ├── bubblegum.colorset
│ │ │ │ └── Contents.json
│ │ │ │ ├── buttercup.colorset
│ │ │ │ └── Contents.json
│ │ │ │ ├── indigo.colorset
│ │ │ │ └── Contents.json
│ │ │ │ ├── lavender.colorset
│ │ │ │ └── Contents.json
│ │ │ │ ├── magenta.colorset
│ │ │ │ └── Contents.json
│ │ │ │ ├── navy.colorset
│ │ │ │ └── Contents.json
│ │ │ │ ├── orange.colorset
│ │ │ │ └── Contents.json
│ │ │ │ ├── oxblood.colorset
│ │ │ │ └── Contents.json
│ │ │ │ ├── periwinkle.colorset
│ │ │ │ └── Contents.json
│ │ │ │ ├── poppy.colorset
│ │ │ │ └── Contents.json
│ │ │ │ ├── purple.colorset
│ │ │ │ └── Contents.json
│ │ │ │ ├── seafoam.colorset
│ │ │ │ └── Contents.json
│ │ │ │ ├── sky.colorset
│ │ │ │ └── Contents.json
│ │ │ │ ├── tan.colorset
│ │ │ │ └── Contents.json
│ │ │ │ ├── teal.colorset
│ │ │ │ └── Contents.json
│ │ │ │ └── yellow.colorset
│ │ │ │ └── Contents.json
│ │ ├── Dependencies
│ │ │ ├── OpenSettings.swift
│ │ │ └── SpeechRecognizer.swift
│ │ ├── Meeting.swift
│ │ ├── Models.swift
│ │ ├── RecordMeeting.swift
│ │ ├── Resources
│ │ │ └── ding.wav
│ │ ├── SyncUpDetail.swift
│ │ ├── SyncUpForm.swift
│ │ └── SyncUpsList.swift
│ ├── SyncUpsTests
│ │ ├── AppFeatureTests.swift
│ │ ├── RecordMeetingTests.swift
│ │ ├── SyncUpDetailTests.swift
│ │ ├── SyncUpFormTests.swift
│ │ └── SyncUpsListTests.swift
│ └── SyncUpsUITests
│ │ └── SyncUpsUITests.swift
├── TicTacToe
│ ├── App
│ │ ├── Assets.xcassets
│ │ │ ├── AppIcon.appiconset
│ │ │ │ ├── AppIcon-60@2x.png
│ │ │ │ ├── AppIcon-76@2x.png
│ │ │ │ ├── AppIcon-iPadPro@2x.png
│ │ │ │ ├── AppIcon.png
│ │ │ │ ├── Contents.json
│ │ │ │ └── transparent.png
│ │ │ └── Contents.json
│ │ ├── RootView.swift
│ │ └── TicTacToeApp.swift
│ ├── README.md
│ ├── TicTacToe.xcodeproj
│ │ ├── project.pbxproj
│ │ ├── project.xcworkspace
│ │ │ ├── contents.xcworkspacedata
│ │ │ └── xcshareddata
│ │ │ │ └── IDEWorkspaceChecks.plist
│ │ └── xcshareddata
│ │ │ └── xcschemes
│ │ │ └── TicTacToe.xcscheme
│ └── tic-tac-toe
│ │ ├── .gitignore
│ │ ├── Package.swift
│ │ ├── Sources
│ │ ├── AppCore
│ │ │ └── AppCore.swift
│ │ ├── AppSwiftUI
│ │ │ └── AppView.swift
│ │ ├── AppUIKit
│ │ │ └── AppViewController.swift
│ │ ├── AuthenticationClient
│ │ │ └── AuthenticationClient.swift
│ │ ├── AuthenticationClientLive
│ │ │ └── LiveAuthenticationClient.swift
│ │ ├── GameCore
│ │ │ ├── GameCore.swift
│ │ │ └── Three.swift
│ │ ├── GameSwiftUI
│ │ │ └── GameView.swift
│ │ ├── GameUIKit
│ │ │ └── GameViewController.swift
│ │ ├── LoginCore
│ │ │ └── LoginCore.swift
│ │ ├── LoginSwiftUI
│ │ │ └── LoginView.swift
│ │ ├── LoginUIKit
│ │ │ └── LoginViewController.swift
│ │ ├── NewGameCore
│ │ │ └── NewGameCore.swift
│ │ ├── NewGameSwiftUI
│ │ │ └── NewGameView.swift
│ │ ├── NewGameUIKit
│ │ │ └── NewGameViewController.swift
│ │ ├── TwoFactorCore
│ │ │ └── TwoFactorCore.swift
│ │ ├── TwoFactorSwiftUI
│ │ │ └── TwoFactorView.swift
│ │ └── TwoFactorUIKit
│ │ │ └── TwoFactorViewController.swift
│ │ └── Tests
│ │ ├── AppCoreTests
│ │ └── AppCoreTests.swift
│ │ ├── GameCoreTests
│ │ └── GameCoreTests.swift
│ │ ├── LoginCoreTests
│ │ └── LoginCoreTests.swift
│ │ ├── NewGameCoreTests
│ │ └── NewGameCoreTests.swift
│ │ └── TwoFactorCoreTests
│ │ └── TwoFactorCoreTests.swift
├── Todos
│ ├── README.md
│ ├── Todos.xcodeproj
│ │ ├── project.pbxproj
│ │ ├── project.xcworkspace
│ │ │ ├── contents.xcworkspacedata
│ │ │ └── xcshareddata
│ │ │ │ └── IDEWorkspaceChecks.plist
│ │ └── xcshareddata
│ │ │ └── xcschemes
│ │ │ └── Todos.xcscheme
│ ├── Todos
│ │ ├── Assets.xcassets
│ │ │ ├── AppIcon.appiconset
│ │ │ │ ├── AppIcon-60@2x.png
│ │ │ │ ├── AppIcon-76@2x.png
│ │ │ │ ├── AppIcon-iPadPro@2x.png
│ │ │ │ ├── AppIcon.png
│ │ │ │ ├── Contents.json
│ │ │ │ └── transparent.png
│ │ │ └── Contents.json
│ │ ├── Todo.swift
│ │ ├── Todos.swift
│ │ └── TodosApp.swift
│ └── TodosTests
│ │ └── TodosTests.swift
└── VoiceMemos
│ ├── README.md
│ ├── VoiceMemos.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ └── IDEWorkspaceChecks.plist
│ └── xcshareddata
│ │ └── xcschemes
│ │ └── VoiceMemos.xcscheme
│ ├── VoiceMemos
│ ├── Assets.xcassets
│ │ ├── AppIcon.appiconset
│ │ │ ├── AppIcon-60@2x.png
│ │ │ ├── AppIcon-76@2x.png
│ │ │ ├── AppIcon-iPadPro@2x.png
│ │ │ ├── AppIcon.png
│ │ │ ├── Contents.json
│ │ │ └── transparent.png
│ │ └── Contents.json
│ ├── AudioPlayerClient
│ │ ├── AudioPlayerClient.swift
│ │ └── LiveAudioPlayerClient.swift
│ ├── AudioRecorderClient
│ │ ├── AudioRecorderClient.swift
│ │ └── LiveAudioRecorderClient.swift
│ ├── Dependencies.swift
│ ├── Helpers.swift
│ ├── Info.plist
│ ├── RecordingMemo.swift
│ ├── VoiceMemo.swift
│ ├── VoiceMemos.swift
│ └── VoiceMemosApp.swift
│ └── VoiceMemosTests
│ └── VoiceMemosTests.swift
├── LICENSE
├── Makefile
├── Package.resolved
├── Package.swift
├── Package@swift-6.0.swift
├── README.md
├── Sources
├── ComposableArchitecture
│ ├── CaseReducer.swift
│ ├── Core.swift
│ ├── Dependencies
│ │ ├── Dismiss.swift
│ │ └── IsPresented.swift
│ ├── Documentation.docc
│ │ ├── Articles
│ │ │ ├── Bindings.md
│ │ │ ├── DependencyManagement.md
│ │ │ ├── FAQ.md
│ │ │ ├── GettingStarted.md
│ │ │ ├── MigrationGuides.md
│ │ │ ├── MigrationGuides
│ │ │ │ ├── MigratingTo1.10.md
│ │ │ │ ├── MigratingTo1.11.md
│ │ │ │ ├── MigratingTo1.12.md
│ │ │ │ ├── MigratingTo1.13.md
│ │ │ │ ├── MigratingTo1.14.md
│ │ │ │ ├── MigratingTo1.15.md
│ │ │ │ ├── MigratingTo1.16.md
│ │ │ │ ├── MigratingTo1.17.1.md
│ │ │ │ ├── MigratingTo1.17.md
│ │ │ │ ├── MigratingTo1.18.md
│ │ │ │ ├── MigratingTo1.19.md
│ │ │ │ ├── MigratingTo1.4.md
│ │ │ │ ├── MigratingTo1.5.md
│ │ │ │ ├── MigratingTo1.6.md
│ │ │ │ ├── MigratingTo1.7.md
│ │ │ │ ├── MigratingTo1.8.md
│ │ │ │ └── MigratingTo1.9.md
│ │ │ ├── Navigation.md
│ │ │ ├── ObservationBackport.md
│ │ │ ├── Performance.md
│ │ │ ├── SharingState.md
│ │ │ ├── StackBasedNavigation.md
│ │ │ ├── SwiftConcurrency.md
│ │ │ ├── TestingTCA.md
│ │ │ ├── TreeBasedNavigation.md
│ │ │ └── WhatIsNavigation.md
│ │ ├── ComposableArchitecture.md
│ │ ├── Extensions
│ │ │ ├── Action.md
│ │ │ ├── Deprecations
│ │ │ │ ├── ReducerDeprecations.md
│ │ │ │ ├── ScopeDeprecations.md
│ │ │ │ ├── StoreDeprecations.md
│ │ │ │ ├── SwiftUIDeprecations.md
│ │ │ │ └── TestStoreDeprecations.md
│ │ │ ├── Effect.md
│ │ │ ├── EffectRun.md
│ │ │ ├── EffectSend.md
│ │ │ ├── IdentifiedAction.md
│ │ │ ├── NavigationLinkState.md
│ │ │ ├── ObservableState.md
│ │ │ ├── Presents.md
│ │ │ ├── Reduce.md
│ │ │ ├── Reducer.md
│ │ │ ├── ReducerBody.md
│ │ │ ├── ReducerBuilder.md
│ │ │ ├── ReducerForEach.md
│ │ │ ├── ReducerMacro.md
│ │ │ ├── ReducerlIfLet.md
│ │ │ ├── ReducerlIfLetPresentation.md
│ │ │ ├── Scope.md
│ │ │ ├── State.md
│ │ │ ├── Store.md
│ │ │ ├── StoreDynamicMemberLookup.md
│ │ │ ├── StoreState.md
│ │ │ ├── SwiftUIBinding.md
│ │ │ ├── SwiftUIBindingScopeForEach.md
│ │ │ ├── SwiftUIBindingScopeIfLet.md
│ │ │ ├── SwiftUIBindingSubscript.md
│ │ │ ├── SwiftUIIntegration.md
│ │ │ ├── SwitchStore.md
│ │ │ ├── TaskResult.md
│ │ │ ├── TestStore.md
│ │ │ ├── TestStoreDependencies.md
│ │ │ ├── TestStoreExhaustivity.md
│ │ │ ├── UIKit.md
│ │ │ ├── ViewStore.md
│ │ │ ├── ViewStoreBinding.md
│ │ │ ├── WithViewStore.md
│ │ │ └── WithViewStoreInit.md
│ │ ├── Resources
│ │ │ ├── 01-02-image-0003.png
│ │ │ ├── 01-02-video-0005.mp4
│ │ │ ├── 01-02-video-0006.mp4
│ │ │ ├── 01-03-image-0005.jpg
│ │ │ ├── 01-homepage.png
│ │ │ ├── 02-01-image-0001.png
│ │ │ ├── 02-02-video-0005.mov
│ │ │ ├── 02-homepage.png
│ │ │ ├── 03-03-video-0006.mp4
│ │ │ ├── ch02-sub01-sec01-image-0001.png
│ │ │ ├── ch02-sub01-sec01-image-0002.png
│ │ │ ├── ch02-sub01-sec03-image-0000.mov
│ │ │ ├── ch02-sub02-sec01-0000.mov
│ │ │ ├── ch02-sub04-sec01-image-0000.png
│ │ │ ├── ch02-sub04-sec01-video-0000.mov
│ │ │ └── ch02-sub04-sec03-video-0000.mp4
│ │ └── Tutorials
│ │ │ ├── BuildingSyncUps
│ │ │ ├── 01-WhatIsSyncUps
│ │ │ │ ├── CreateProject-0001-image.png
│ │ │ │ ├── CreateProject-0002-image.png
│ │ │ │ ├── CreateProject-0003-image.png
│ │ │ │ ├── CreateProject-0004-image.png
│ │ │ │ ├── TourOfSyncUps-0003-image.png
│ │ │ │ ├── TourOfSyncUps-0004-image.png
│ │ │ │ ├── TourOfSyncUps-0005-image.png
│ │ │ │ ├── TourOfSyncUps-0006-image.png
│ │ │ │ ├── TourOfSyncUps-0007-image.png
│ │ │ │ ├── TourOfSyncUps-0008-image.png
│ │ │ │ ├── TourOfSyncUps-0009-image.png
│ │ │ │ ├── TourOfSyncUps-0010-image.png
│ │ │ │ ├── TourOfSyncUps-0011-image.png
│ │ │ │ ├── TourOfSyncUps-0012-image.png
│ │ │ │ ├── TourOfSyncUps-0013-image.png
│ │ │ │ ├── TourOfSyncUps-0014-image.png
│ │ │ │ └── WhatIsSyncUps.tutorial
│ │ │ ├── 02-ListsOfSyncUps
│ │ │ │ ├── ListsOfSyncUps-01-code-0001.swift
│ │ │ │ ├── ListsOfSyncUps-01-code-0002.swift
│ │ │ │ ├── ListsOfSyncUps-01-code-0003.swift
│ │ │ │ ├── ListsOfSyncUps-01-code-0004.swift
│ │ │ │ ├── ListsOfSyncUps-02-code-0001.swift
│ │ │ │ ├── ListsOfSyncUps-02-code-0002.swift
│ │ │ │ ├── ListsOfSyncUps-02-code-0003.swift
│ │ │ │ ├── ListsOfSyncUps-02-code-0004.swift
│ │ │ │ ├── ListsOfSyncUps-02-code-0005.swift
│ │ │ │ ├── ListsOfSyncUps-02-code-0006-previous.swift
│ │ │ │ ├── ListsOfSyncUps-02-code-0006.swift
│ │ │ │ ├── ListsOfSyncUps-02-code-0007.swift
│ │ │ │ ├── ListsOfSyncUps-02-code-0008.swift
│ │ │ │ ├── ListsOfSyncUps-02-code-0009.swift
│ │ │ │ ├── ListsOfSyncUps-02-code-0010.mp4
│ │ │ │ ├── ListsOfSyncUps-03-code-0001-previous.swift
│ │ │ │ ├── ListsOfSyncUps-03-code-0001.swift
│ │ │ │ ├── ListsOfSyncUps-03-code-0002.diff
│ │ │ │ ├── ListsOfSyncUps-cover.png
│ │ │ │ ├── ListsOfSyncUps.tutorial
│ │ │ │ ├── TestingListOfSyncUps-01-code-0001.swift
│ │ │ │ ├── TestingListOfSyncUps-01-code-0002.swift
│ │ │ │ ├── TestingListOfSyncUps-01-code-0003.swift
│ │ │ │ ├── TestingListOfSyncUps-01-code-0004.swift
│ │ │ │ └── TestingListOfSyncUps.tutorial
│ │ │ ├── 03-SyncUpForm
│ │ │ │ ├── SyncUpForm-01-code-0001.swift
│ │ │ │ ├── SyncUpForm-01-code-0002.swift
│ │ │ │ ├── SyncUpForm-01-code-0003.swift
│ │ │ │ ├── SyncUpForm-01-code-0004.swift
│ │ │ │ ├── SyncUpForm-01-code-0005.swift
│ │ │ │ ├── SyncUpForm-01-code-0006.swift
│ │ │ │ ├── SyncUpForm-01-code-0007.swift
│ │ │ │ ├── SyncUpForm-01-code-0008.swift
│ │ │ │ ├── SyncUpForm-01-code-0009.swift
│ │ │ │ ├── SyncUpForm-02-code-0001-previous.swift
│ │ │ │ ├── SyncUpForm-02-code-0001.swift
│ │ │ │ ├── SyncUpForm-02-code-0002.swift
│ │ │ │ ├── SyncUpForm-02-code-0003.swift
│ │ │ │ ├── SyncUpForm-02-code-0004.swift
│ │ │ │ ├── SyncUpForm-02-code-0005.swift
│ │ │ │ ├── SyncUpForm-02-code-0006.swift
│ │ │ │ ├── SyncUpForm-02-video-0007.mp4
│ │ │ │ ├── SyncUpForm-03-code-0001-previous.swift
│ │ │ │ ├── SyncUpForm-03-code-0001.swift
│ │ │ │ ├── SyncUpForm-03-code-0002.swift
│ │ │ │ ├── SyncUpForm-03-code-0003.swift
│ │ │ │ ├── SyncUpForm-03-code-0004-previous.swift
│ │ │ │ ├── SyncUpForm-03-code-0004.swift
│ │ │ │ ├── SyncUpForm-03-code-0005.swift
│ │ │ │ ├── SyncUpForm.tutorial
│ │ │ │ ├── SyncUpFormBasics-01-0000.png
│ │ │ │ ├── TestingSyncUpForm-01-code-0001.swift
│ │ │ │ ├── TestingSyncUpForm-01-code-0002.swift
│ │ │ │ ├── TestingSyncUpForm-01-code-0003.swift
│ │ │ │ ├── TestingSyncUpForm-01-code-0004-previous.swift
│ │ │ │ ├── TestingSyncUpForm-01-code-0004.swift
│ │ │ │ ├── TestingSyncUpForm-01-code-0005.swift
│ │ │ │ ├── TestingSyncUpForm-02-code-0001-previous.swift
│ │ │ │ ├── TestingSyncUpForm-02-code-0001.swift
│ │ │ │ ├── TestingSyncUpForm-02-code-0002.swift
│ │ │ │ ├── TestingSyncUpForm-02-code-0003.swift
│ │ │ │ ├── TestingSyncUpForm-02-code-0004-previous.swift
│ │ │ │ ├── TestingSyncUpForm-02-code-0004.swift
│ │ │ │ ├── TestingSyncUpForm-02-code-0005.swift
│ │ │ │ ├── TestingSyncUpForm-02-code-0006-previous.swift
│ │ │ │ ├── TestingSyncUpForm-02-code-0006.swift
│ │ │ │ ├── TestingSyncUpForm-02-code-0007.swift
│ │ │ │ └── TestingSyncUpForm.tutorial
│ │ │ ├── 04-PresentingSyncUpForm
│ │ │ │ ├── PresentingSyncUpForm-01-code-0001-previous.swift
│ │ │ │ ├── PresentingSyncUpForm-01-code-0001.swift
│ │ │ │ ├── PresentingSyncUpForm-01-code-0002.swift
│ │ │ │ ├── PresentingSyncUpForm-01-code-0003.swift
│ │ │ │ ├── PresentingSyncUpForm-01-code-0004.swift
│ │ │ │ ├── PresentingSyncUpForm-01-code-0005.swift
│ │ │ │ ├── PresentingSyncUpForm-02-code-0001-previous.swift
│ │ │ │ ├── PresentingSyncUpForm-02-code-0001.swift
│ │ │ │ ├── PresentingSyncUpForm-02-code-0002.swift
│ │ │ │ ├── PresentingSyncUpForm-02-code-0003.swift
│ │ │ │ ├── PresentingSyncUpForm-02-video-0004.mov
│ │ │ │ ├── PresentingSyncUpForm-03-code-0001-previous.swift
│ │ │ │ ├── PresentingSyncUpForm-03-code-0001.swift
│ │ │ │ ├── PresentingSyncUpForm-03-code-0002.swift
│ │ │ │ ├── PresentingSyncUpForm-03-code-0003-previous.swift
│ │ │ │ ├── PresentingSyncUpForm-03-code-0003.swift
│ │ │ │ ├── PresentingSyncUpForm-03-code-0004.swift
│ │ │ │ ├── PresentingSyncUpForm-03-code-0005.swift
│ │ │ │ ├── PresentingSyncUpForm-03-code-0006.mov
│ │ │ │ ├── PresentingSyncUpForm.tutorial
│ │ │ │ ├── TestingSyncUpFormPresentation-01-code-0001-previous.swift
│ │ │ │ ├── TestingSyncUpFormPresentation-01-code-0001.swift
│ │ │ │ ├── TestingSyncUpFormPresentation-01-code-0002.swift
│ │ │ │ ├── TestingSyncUpFormPresentation-01-code-0003.swift
│ │ │ │ ├── TestingSyncUpFormPresentation-01-code-0004.swift
│ │ │ │ ├── TestingSyncUpFormPresentation-01-code-0005-previous.swift
│ │ │ │ ├── TestingSyncUpFormPresentation-01-code-0005.swift
│ │ │ │ ├── TestingSyncUpFormPresentation-01-code-0006.swift
│ │ │ │ ├── TestingSyncUpFormPresentation-01-code-0007-previous.swift
│ │ │ │ ├── TestingSyncUpFormPresentation-01-code-0007.swift
│ │ │ │ ├── TestingSyncUpFormPresentation-01-code-0008.swift
│ │ │ │ ├── TestingSyncUpFormPresentation-01-code-0009.swift
│ │ │ │ ├── TestingSyncUpFormPresentation-01-code-0010.swift
│ │ │ │ ├── TestingSyncUpFormPresentation-01-code-0011.swift
│ │ │ │ ├── TestingSyncUpFormPresentation-01-code-0012.swift
│ │ │ │ ├── TestingSyncUpFormPresentation-01-code-0013.swift
│ │ │ │ ├── TestingSyncUpFormPresentation-01-code-0014.swift
│ │ │ │ ├── TestingSyncUpFormPresentation-02-code-0001-previous.swift
│ │ │ │ ├── TestingSyncUpFormPresentation-02-code-0001.swift
│ │ │ │ ├── TestingSyncUpFormPresentation-02-code-0002.swift
│ │ │ │ ├── TestingSyncUpFormPresentation-02-code-0003.swift
│ │ │ │ ├── TestingSyncUpFormPresentation-02-code-0004.swift
│ │ │ │ ├── TestingSyncUpFormPresentation-02-code-0005.swift
│ │ │ │ ├── TestingSyncUpFormPresentation-02-code-0006.swift
│ │ │ │ └── TestingSyncUpFormPresentation.tutorial
│ │ │ ├── 05-PersistingSyncUps
│ │ │ │ ├── PersistingSyncUps-01-code-0001-previous.swift
│ │ │ │ ├── PersistingSyncUps-01-code-0001.swift
│ │ │ │ ├── PersistingSyncUps-01-code-0002.swift
│ │ │ │ ├── PersistingSyncUps-01-code-0003.swift
│ │ │ │ ├── PersistingSyncUps-01-code-0004.swift
│ │ │ │ ├── PersistingSyncUps-01-code-0005.swift
│ │ │ │ ├── PersistingSyncUps-01-code-0006-previous.swift
│ │ │ │ ├── PersistingSyncUps-01-code-0006.swift
│ │ │ │ ├── PersistingSyncUps-01-code-0007.swift
│ │ │ │ ├── PersistingSyncUps-01-video-0008.mov
│ │ │ │ ├── PersistingSyncUps-02-code-0001-previous.swift
│ │ │ │ ├── PersistingSyncUps-02-code-0001.swift
│ │ │ │ ├── PersistingSyncUps-02-code-0002.swift
│ │ │ │ ├── PersistingSyncUps-02-code-0003.swift
│ │ │ │ └── PersistingSyncUps.tutorial
│ │ │ ├── 06-SyncUpDetail
│ │ │ │ ├── EditingAndDeletingSyncUp-01-code-0001-previous.swift
│ │ │ │ ├── EditingAndDeletingSyncUp-01-code-0001.swift
│ │ │ │ ├── EditingAndDeletingSyncUp-01-code-0002.swift
│ │ │ │ ├── EditingAndDeletingSyncUp-01-code-0003.swift
│ │ │ │ ├── EditingAndDeletingSyncUp-01-code-0004.swift
│ │ │ │ ├── EditingAndDeletingSyncUp-01-code-0005-previous.swift
│ │ │ │ ├── EditingAndDeletingSyncUp-01-code-0005.swift
│ │ │ │ ├── EditingAndDeletingSyncUp-01-code-0006.swift
│ │ │ │ ├── EditingAndDeletingSyncUp-01-code-0007.swift
│ │ │ │ ├── EditingAndDeletingSyncUp-01-code-0008.swift
│ │ │ │ ├── EditingAndDeletingSyncUp-01-code-0009-previous.swift
│ │ │ │ ├── EditingAndDeletingSyncUp-01-code-0009.swift
│ │ │ │ ├── EditingAndDeletingSyncUp-01-code-0010.swift
│ │ │ │ ├── EditingAndDeletingSyncUp-01-code-0011.swift
│ │ │ │ ├── EditingAndDeletingSyncUp-01-cover-480p.mov
│ │ │ │ ├── EditingAndDeletingSyncUp-02-code-0001-previous.swift
│ │ │ │ ├── EditingAndDeletingSyncUp-02-code-0001.swift
│ │ │ │ ├── EditingAndDeletingSyncUp-02-code-0002.swift
│ │ │ │ ├── EditingAndDeletingSyncUp-02-code-0003.swift
│ │ │ │ ├── EditingAndDeletingSyncUp-02-code-0004.swift
│ │ │ │ ├── EditingAndDeletingSyncUp-02-code-0005.swift
│ │ │ │ ├── EditingAndDeletingSyncUp-02-code-0006.swift
│ │ │ │ ├── EditingAndDeletingSyncUp-02-code-0007.swift
│ │ │ │ ├── EditingAndDeletingSyncUp-02-code-0008.swift
│ │ │ │ ├── EditingAndDeletingSyncUp-02-code-0009.swift
│ │ │ │ ├── EditingAndDeletingSyncUp-02-code-0010.swift
│ │ │ │ ├── EditingAndDeletingSyncUp-02-code-0011.swift
│ │ │ │ ├── EditingAndDeletingSyncUp-02-code-0012.swift
│ │ │ │ ├── EditingAndDeletingSyncUp-02-code-0013.swift
│ │ │ │ ├── EditingAndDeletingSyncUp-02-code-0014-previous.swift
│ │ │ │ ├── EditingAndDeletingSyncUp-02-code-0014.swift
│ │ │ │ ├── EditingAndDeletingSyncUp-02-cover-480p.mov
│ │ │ │ ├── EditingAndDeletingSyncUp-03-code-0001-previous.swift
│ │ │ │ ├── EditingAndDeletingSyncUp-03-code-0001.swift
│ │ │ │ ├── EditingAndDeletingSyncUp-03-code-0002.swift
│ │ │ │ ├── EditingAndDeletingSyncUp-03-code-0003-previous.swift
│ │ │ │ ├── EditingAndDeletingSyncUp-03-code-0003.swift
│ │ │ │ ├── EditingAndDeletingSyncUp-03-code-0004.swift
│ │ │ │ ├── EditingAndDeletingSyncUp-03-code-0005.swift
│ │ │ │ ├── EditingAndDeletingSyncUp-03-code-0006.swift
│ │ │ │ ├── EditingAndDeletingSyncUp-03-code-0007.swift
│ │ │ │ ├── EditingAndDeletingSyncUp-03-code-0008.swift
│ │ │ │ ├── EditingAndDeletingSyncUp-03-code-0009.swift
│ │ │ │ ├── EditingAndDeletingSyncUp-03-code-0010.swift
│ │ │ │ ├── EditingAndDeletingSyncUp-03-code-0011.swift
│ │ │ │ ├── EditingAndDeletingSyncUp-03-code-0012.swift
│ │ │ │ ├── EditingAndDeletingSyncUp-03-code-0013-previous.swift
│ │ │ │ ├── EditingAndDeletingSyncUp-03-code-0013.swift
│ │ │ │ ├── EditingAndDeletingSyncUp.tutorial
│ │ │ │ ├── SyncUpDetail-01-code-0001.swift
│ │ │ │ ├── SyncUpDetail-01-code-0002.swift
│ │ │ │ ├── SyncUpDetail-01-code-0003.swift
│ │ │ │ ├── SyncUpDetail-01-code-0004.swift
│ │ │ │ ├── SyncUpDetail-01-code-0005.swift
│ │ │ │ ├── SyncUpDetail-01-code-0006.swift
│ │ │ │ ├── SyncUpDetail-01-code-0007.swift
│ │ │ │ ├── SyncUpDetail-01-image-0007.png
│ │ │ │ ├── SyncUpDetail-cover.png
│ │ │ │ ├── SyncUpDetail.tutorial
│ │ │ │ ├── TestingSyncUpDetail-01-code-0001.swift
│ │ │ │ ├── TestingSyncUpDetail-01-code-0002.swift
│ │ │ │ ├── TestingSyncUpDetail-01-code-0003.swift
│ │ │ │ ├── TestingSyncUpDetail-01-code-0004.swift
│ │ │ │ ├── TestingSyncUpDetail-01-code-0005.swift
│ │ │ │ ├── TestingSyncUpDetail-01-code-0006.swift
│ │ │ │ └── TestingSyncUpDetail.tutorial
│ │ │ ├── 07-SyncUpDetailNavigation
│ │ │ │ ├── MeetingNavigation-01-code-0001.swift
│ │ │ │ ├── MeetingNavigation-01-code-0002.swift
│ │ │ │ ├── MeetingNavigation-01-code-0003.swift
│ │ │ │ ├── MeetingNavigation-01-cover.png
│ │ │ │ ├── MeetingNavigation-02-code-0001.swift
│ │ │ │ ├── MeetingNavigation-02-code-0002.swift
│ │ │ │ ├── MeetingNavigation-02-code-0003-previous.swift
│ │ │ │ ├── MeetingNavigation-02-code-0003.swift
│ │ │ │ ├── MeetingNavigation-02-code-0004-previous.swift
│ │ │ │ ├── MeetingNavigation-02-code-0004.swift
│ │ │ │ ├── MeetingNavigation.tutorial
│ │ │ │ ├── SyncUpDetailNavigation-01-code-0001.swift
│ │ │ │ ├── SyncUpDetailNavigation-01-code-0002.swift
│ │ │ │ ├── SyncUpDetailNavigation-01-code-0003.swift
│ │ │ │ ├── SyncUpDetailNavigation-01-code-0004.swift
│ │ │ │ ├── SyncUpDetailNavigation-01-code-0005.swift
│ │ │ │ ├── SyncUpDetailNavigation-01-code-0006.swift
│ │ │ │ ├── SyncUpDetailNavigation-01-code-0007.swift
│ │ │ │ ├── SyncUpDetailNavigation-01-code-0008.swift
│ │ │ │ ├── SyncUpDetailNavigation-02-code-0001-previous.swift
│ │ │ │ ├── SyncUpDetailNavigation-02-code-0001.swift
│ │ │ │ ├── SyncUpDetailNavigation-02-code-0002.swift
│ │ │ │ ├── SyncUpDetailNavigation-02-code-0003.swift
│ │ │ │ ├── SyncUpDetailNavigation-02-code-0004.swift
│ │ │ │ ├── SyncUpDetailNavigation-02-code-0005.swift
│ │ │ │ ├── SyncUpDetailNavigation-02-code-0006.swift
│ │ │ │ ├── SyncUpDetailNavigation-02-code-0007.swift
│ │ │ │ ├── SyncUpDetailNavigation-03-code-0001-previous.swift
│ │ │ │ ├── SyncUpDetailNavigation-03-code-0001.swift
│ │ │ │ ├── SyncUpDetailNavigation-03-code-0002.swift
│ │ │ │ ├── SyncUpDetailNavigation-03-code-0003.swift
│ │ │ │ ├── SyncUpDetailNavigation-03-code-0004.swift
│ │ │ │ ├── SyncUpDetailNavigation-03-video-0005.mov
│ │ │ │ ├── SyncUpDetailNavigation-03-video-0006.mov
│ │ │ │ ├── SyncUpDetailNavigation.tutorial
│ │ │ │ ├── TestingNavigation-01-code-0001.swift
│ │ │ │ ├── TestingNavigation-01-code-0002.swift
│ │ │ │ ├── TestingNavigation-01-code-0003.swift
│ │ │ │ ├── TestingNavigation-01-code-0004.swift
│ │ │ │ ├── TestingNavigation-01-code-0005.swift
│ │ │ │ ├── TestingNavigation-01-code-0006.swift
│ │ │ │ ├── TestingNavigation-01-code-0007.swift
│ │ │ │ ├── TestingNavigation-01-code-0008.swift
│ │ │ │ └── TestingNavigation.tutorial
│ │ │ ├── 08-RecordMeeting
│ │ │ │ ├── ImplementingSpeechRecognizer.tutorial
│ │ │ │ ├── ImplementingTimer-01-code-0001-previous.swift
│ │ │ │ ├── ImplementingTimer-01-code-0001.swift
│ │ │ │ ├── ImplementingTimer-01-code-0002.swift
│ │ │ │ ├── ImplementingTimer-01-code-0003.swift
│ │ │ │ ├── ImplementingTimer-01-code-0004.swift
│ │ │ │ ├── ImplementingTimer-01-code-0005.swift
│ │ │ │ ├── ImplementingTimer-01-code-0006.swift
│ │ │ │ ├── ImplementingTimer-01-code-0007.swift
│ │ │ │ ├── ImplementingTimer-01-code-0008.swift
│ │ │ │ ├── ImplementingTimer-01-code-0009.swift
│ │ │ │ ├── ImplementingTimer-01-code-0010.swift
│ │ │ │ ├── ImplementingTimer-01-code-0011-previous.swift
│ │ │ │ ├── ImplementingTimer-01-code-0011.swift
│ │ │ │ ├── ImplementingTimer-01-video-0012.mov
│ │ │ │ ├── ImplementingTimer-02-code-0001-previous.swift
│ │ │ │ ├── ImplementingTimer-02-code-0001.swift
│ │ │ │ ├── ImplementingTimer-02-code-0002.swift
│ │ │ │ ├── ImplementingTimer-02-code-0003.swift
│ │ │ │ ├── ImplementingTimer-02-code-0004.swift
│ │ │ │ ├── ImplementingTimer-03-code-0001-previous.swift
│ │ │ │ ├── ImplementingTimer-03-code-0001.swift
│ │ │ │ ├── ImplementingTimer-03-code-0002.swift
│ │ │ │ ├── ImplementingTimer-03-code-0003.swift
│ │ │ │ ├── ImplementingTimer-03-code-0004.swift
│ │ │ │ ├── ImplementingTimer-03-code-0005.swift
│ │ │ │ ├── ImplementingTimer-03-code-0006.swift
│ │ │ │ ├── ImplementingTimer-03-code-0007.swift
│ │ │ │ ├── ImplementingTimer-03-code-0008.swift
│ │ │ │ ├── ImplementingTimer-03-video-0009.mov
│ │ │ │ ├── ImplementingTimer-04-code-0001.swift
│ │ │ │ ├── ImplementingTimer-04-code-0002.swift
│ │ │ │ ├── ImplementingTimer-04-code-0003.swift
│ │ │ │ ├── ImplementingTimer-04-code-0004.swift
│ │ │ │ ├── ImplementingTimer-04-code-0005.swift
│ │ │ │ ├── ImplementingTimer-04-code-0006.swift
│ │ │ │ ├── ImplementingTimer-04-code-0007.swift
│ │ │ │ ├── ImplementingTimer-04-code-0008.swift
│ │ │ │ ├── ImplementingTimer-04-code-0009.swift
│ │ │ │ ├── ImplementingTimer-04-code-0010.swift
│ │ │ │ ├── ImplementingTimer-04-code-0011.swift
│ │ │ │ ├── ImplementingTimer-04-code-0012.swift
│ │ │ │ ├── ImplementingTimer-04-code-0013.swift
│ │ │ │ ├── ImplementingTimer-04-code-0014.swift
│ │ │ │ ├── ImplementingTimer-04-code-0015.swift
│ │ │ │ ├── ImplementingTimer-04-code-0016.swift
│ │ │ │ ├── ImplementingTimer-04-code-0017.swift
│ │ │ │ ├── ImplementingTimer.tutorial
│ │ │ │ ├── RecordMeetingFeature-01-code-0001.swift
│ │ │ │ ├── RecordMeetingFeature-01-code-0002.swift
│ │ │ │ ├── RecordMeetingFeature-01-code-0003.swift
│ │ │ │ ├── RecordMeetingFeature-01-image-0004.jpg
│ │ │ │ ├── RecordMeetingFeature-02-code-0001-previous.swift
│ │ │ │ ├── RecordMeetingFeature-02-code-0001.swift
│ │ │ │ ├── RecordMeetingFeature-02-code-0002-previous.swift
│ │ │ │ ├── RecordMeetingFeature-02-code-0002.swift
│ │ │ │ ├── RecordMeetingFeature-02-code-0003-previous.swift
│ │ │ │ ├── RecordMeetingFeature-02-code-0003.swift
│ │ │ │ ├── RecordMeetingFeature-02-video-0004.mov
│ │ │ │ └── RecordMeetingFeature.tutorial
│ │ │ └── BuildingSyncUps.tutorial
│ │ │ └── MeetTheComposableArchitecture
│ │ │ ├── 01-Essentials
│ │ │ ├── 01-YourFirstFeature
│ │ │ │ ├── 01-01-01-code-0001.swift
│ │ │ │ ├── 01-01-01-code-0002.swift
│ │ │ │ ├── 01-01-01-code-0003.swift
│ │ │ │ ├── 01-01-01-code-0004.swift
│ │ │ │ ├── 01-01-01-code-0005.swift
│ │ │ │ ├── 01-01-01-code-0006.swift
│ │ │ │ ├── 01-01-02-code-0001.swift
│ │ │ │ ├── 01-01-02-code-0002.swift
│ │ │ │ ├── 01-01-02-code-0003.swift
│ │ │ │ ├── 01-01-02-code-0004.swift
│ │ │ │ ├── 01-01-02-code-0005.swift
│ │ │ │ ├── 01-01-02-code-0006.swift
│ │ │ │ ├── 01-01-02-code-0007.swift
│ │ │ │ ├── 01-01-03-code-0001.swift
│ │ │ │ ├── 01-01-03-code-0002.swift
│ │ │ │ ├── 01-01-03-code-0003.swift
│ │ │ │ ├── 01-01-03-code-0004.swift
│ │ │ │ └── 01-01-YourFirstFeature.tutorial
│ │ │ ├── 02-AddingSideEffects
│ │ │ │ ├── 01-02-01-code-0001-previous.swift
│ │ │ │ ├── 01-02-01-code-0001.swift
│ │ │ │ ├── 01-02-01-code-0002.swift
│ │ │ │ ├── 01-02-01-code-0003.swift
│ │ │ │ ├── 01-02-01-code-0004.swift
│ │ │ │ ├── 01-02-01-code-0005.swift
│ │ │ │ ├── 01-02-02-code-0001.swift
│ │ │ │ ├── 01-02-02-code-0002.swift
│ │ │ │ ├── 01-02-02-code-0003.swift
│ │ │ │ ├── 01-02-02-code-0004.swift
│ │ │ │ ├── 01-02-02-code-0005.swift
│ │ │ │ ├── 01-02-03-code-0001.swift
│ │ │ │ ├── 01-02-03-code-0002.swift
│ │ │ │ ├── 01-02-03-code-0003.swift
│ │ │ │ ├── 01-02-03-code-0004.swift
│ │ │ │ ├── 01-02-03-code-0005.swift
│ │ │ │ ├── 01-02-03-code-0006.swift
│ │ │ │ └── 01-02-AddingSideEffects.tutorial
│ │ │ ├── 03-TestingYourFeatures
│ │ │ │ ├── 01-03-01-code-0001.swift
│ │ │ │ ├── 01-03-01-code-0002.swift
│ │ │ │ ├── 01-03-01-code-0003-previous.swift
│ │ │ │ ├── 01-03-01-code-0003.swift
│ │ │ │ ├── 01-03-01-code-0004.swift
│ │ │ │ ├── 01-03-01-code-0005.swift
│ │ │ │ ├── 01-03-01-code-0006.swift
│ │ │ │ ├── 01-03-02-code-0001-previous.swift
│ │ │ │ ├── 01-03-02-code-0001.swift
│ │ │ │ ├── 01-03-02-code-0002.swift
│ │ │ │ ├── 01-03-02-code-0003.swift
│ │ │ │ ├── 01-03-02-code-0004.swift
│ │ │ │ ├── 01-03-02-code-0005.swift
│ │ │ │ ├── 01-03-02-code-0006.swift
│ │ │ │ ├── 01-03-02-code-0007.swift
│ │ │ │ ├── 01-03-02-code-0008.swift
│ │ │ │ ├── 01-03-02-code-0009.swift
│ │ │ │ ├── 01-03-02-code-0010.swift
│ │ │ │ ├── 01-03-03-code-0001-previous.swift
│ │ │ │ ├── 01-03-03-code-0001.swift
│ │ │ │ ├── 01-03-03-code-0002.swift
│ │ │ │ ├── 01-03-03-code-0003.swift
│ │ │ │ ├── 01-03-03-code-0004.swift
│ │ │ │ ├── 01-03-03-code-0005.swift
│ │ │ │ ├── 01-03-04-code-0001.swift
│ │ │ │ ├── 01-03-04-code-0002.swift
│ │ │ │ ├── 01-03-04-code-0003.swift
│ │ │ │ ├── 01-03-04-code-0004.swift
│ │ │ │ ├── 01-03-04-code-0005.swift
│ │ │ │ ├── 01-03-04-code-0006-previous.swift
│ │ │ │ ├── 01-03-04-code-0006.swift
│ │ │ │ ├── 01-03-04-code-0007.swift
│ │ │ │ ├── 01-03-04-code-0008.swift
│ │ │ │ └── 01-03-TestingYourFeature.tutorial
│ │ │ └── 04-ComposingFeatures
│ │ │ │ ├── 01-04-01-code-0001.swift
│ │ │ │ ├── 01-04-01-code-0002.swift
│ │ │ │ ├── 01-04-01-code-0003.swift
│ │ │ │ ├── 01-04-02-code-0001.swift
│ │ │ │ ├── 01-04-02-code-0002.swift
│ │ │ │ ├── 01-04-02-code-0003.swift
│ │ │ │ ├── 01-04-02-code-0004.swift
│ │ │ │ ├── 01-04-02-code-0005.swift
│ │ │ │ ├── 01-04-02-code-0006.swift
│ │ │ │ ├── 01-04-02-code-0007.swift
│ │ │ │ ├── 01-04-02-code-0008.swift
│ │ │ │ ├── 01-04-03-code-0001-previous.swift
│ │ │ │ ├── 01-04-03-code-0001.swift
│ │ │ │ ├── 01-04-03-code-0002.swift
│ │ │ │ ├── 01-04-03-code-0003.swift
│ │ │ │ ├── 01-04-03-code-0004.swift
│ │ │ │ ├── 01-04-03-code-0005-previous.swift
│ │ │ │ ├── 01-04-03-code-0005.swift
│ │ │ │ └── 01-04-ComposingFeatures.tutorial
│ │ │ ├── 02-Navigation
│ │ │ ├── 01-YourFirstPresentation
│ │ │ │ ├── 02-01-01-code-0000.swift
│ │ │ │ ├── 02-01-01-code-0001.swift
│ │ │ │ ├── 02-01-01-code-0002.swift
│ │ │ │ ├── 02-01-01-code-0003.swift
│ │ │ │ ├── 02-01-01-code-0004.swift
│ │ │ │ ├── 02-01-01-code-0005.swift
│ │ │ │ ├── 02-01-01-code-0006.swift
│ │ │ │ ├── 02-01-01-code-0007.swift
│ │ │ │ ├── 02-01-02-code-0000.swift
│ │ │ │ ├── 02-01-02-code-0001.swift
│ │ │ │ ├── 02-01-02-code-0002.swift
│ │ │ │ ├── 02-01-02-code-0003.swift
│ │ │ │ ├── 02-01-02-code-0004.swift
│ │ │ │ ├── 02-01-02-code-0005.swift
│ │ │ │ ├── 02-01-02-code-0006.swift
│ │ │ │ ├── 02-01-02-code-0007.swift
│ │ │ │ ├── 02-01-02-code-0008.swift
│ │ │ │ ├── 02-01-02-code-0009.swift
│ │ │ │ ├── 02-01-04-code-0000-previous.swift
│ │ │ │ ├── 02-01-04-code-0000.swift
│ │ │ │ ├── 02-01-04-code-0001.swift
│ │ │ │ ├── 02-01-04-code-0002.swift
│ │ │ │ ├── 02-01-04-code-0003-previous.swift
│ │ │ │ ├── 02-01-04-code-0003.swift
│ │ │ │ ├── 02-01-04-code-0004-previous.swift
│ │ │ │ ├── 02-01-04-code-0004.swift
│ │ │ │ ├── 02-01-04-code-0005.swift
│ │ │ │ ├── 02-01-04-code-0006.swift
│ │ │ │ ├── 02-01-04-code-0007-previous.swift
│ │ │ │ ├── 02-01-04-code-0007.swift
│ │ │ │ └── 02-01-YourFirstPresentation.tutorial
│ │ │ ├── 02-MultipleDestinations
│ │ │ │ ├── 02-02-01-code-0000-previous.swift
│ │ │ │ ├── 02-02-01-code-0000.swift
│ │ │ │ ├── 02-02-01-code-0001.swift
│ │ │ │ ├── 02-02-01-code-0002.swift
│ │ │ │ ├── 02-02-01-code-0003.swift
│ │ │ │ ├── 02-02-01-code-0004.swift
│ │ │ │ ├── 02-02-01-code-0005.swift
│ │ │ │ ├── 02-02-01-code-0006-previous.swift
│ │ │ │ ├── 02-02-01-code-0006.swift
│ │ │ │ ├── 02-02-01-code-0007.swift
│ │ │ │ ├── 02-02-02-code-0000.swift
│ │ │ │ ├── 02-02-02-code-0001.swift
│ │ │ │ ├── 02-02-02-code-0002.swift
│ │ │ │ ├── 02-02-02-code-0003-previous.swift
│ │ │ │ ├── 02-02-02-code-0003.swift
│ │ │ │ ├── 02-02-02-code-0004-previous.swift
│ │ │ │ ├── 02-02-02-code-0004.swift
│ │ │ │ ├── 02-02-02-code-0005-previous.swift
│ │ │ │ ├── 02-02-02-code-0005.swift
│ │ │ │ ├── 02-02-02-code-0006.swift
│ │ │ │ ├── 02-02-02-code-0007.swift
│ │ │ │ ├── 02-02-02-code-0008.swift
│ │ │ │ ├── 02-02-02-code-0009.swift
│ │ │ │ ├── 02-02-02-code-0010.swift
│ │ │ │ ├── 02-02-02-code-0011.swift
│ │ │ │ ├── 02-02-02-code-0012-previous.swift
│ │ │ │ ├── 02-02-02-code-0012.swift
│ │ │ │ ├── 02-02-02-code-0013.swift
│ │ │ │ └── 02-02-MultipleDestinations.tutorial
│ │ │ ├── 03-TestingPresentation
│ │ │ │ ├── 02-03-01-code-0000.swift
│ │ │ │ ├── 02-03-01-code-0001.swift
│ │ │ │ ├── 02-03-01-code-0002.swift
│ │ │ │ ├── 02-03-01-code-0003.swift
│ │ │ │ ├── 02-03-01-code-0004.swift
│ │ │ │ ├── 02-03-01-code-0005.swift
│ │ │ │ ├── 02-03-01-code-0006-previous.swift
│ │ │ │ ├── 02-03-01-code-0006.swift
│ │ │ │ ├── 02-03-01-code-0007.swift
│ │ │ │ ├── 02-03-01-code-0008-previous.swift
│ │ │ │ ├── 02-03-01-code-0008.swift
│ │ │ │ ├── 02-03-01-code-0009.swift
│ │ │ │ ├── 02-03-01-code-0010.swift
│ │ │ │ ├── 02-03-01-code-0011.swift
│ │ │ │ ├── 02-03-01-code-0012.swift
│ │ │ │ ├── 02-03-01-code-0013.swift
│ │ │ │ ├── 02-03-01-code-0014.swift
│ │ │ │ ├── 02-03-01-code-0015-previous.swift
│ │ │ │ ├── 02-03-01-code-0015.swift
│ │ │ │ ├── 02-03-01-code-0016.swift
│ │ │ │ ├── 02-03-01-code-0017.swift
│ │ │ │ ├── 02-03-02-code-0000.swift
│ │ │ │ ├── 02-03-02-code-0001.swift
│ │ │ │ ├── 02-03-02-code-0002.swift
│ │ │ │ ├── 02-03-02-code-0003.swift
│ │ │ │ ├── 02-03-02-code-0004.swift
│ │ │ │ ├── 02-03-02-code-0005.swift
│ │ │ │ ├── 02-03-02-code-0006.swift
│ │ │ │ ├── 02-03-03-code-0000.swift
│ │ │ │ ├── 02-03-03-code-0001.swift
│ │ │ │ ├── 02-03-03-code-0002.swift
│ │ │ │ ├── 02-03-03-code-0003.swift
│ │ │ │ ├── 02-03-03-code-0004.swift
│ │ │ │ ├── 02-03-03-code-0005.swift
│ │ │ │ ├── 02-03-03-code-0006.swift
│ │ │ │ ├── 02-03-03-code-0007-previous.swift
│ │ │ │ ├── 02-03-03-code-0007.swift
│ │ │ │ ├── 02-03-03-code-0008-previous.swift
│ │ │ │ ├── 02-03-03-code-0008.swift
│ │ │ │ ├── 02-03-03-code-0009.swift
│ │ │ │ ├── 02-03-03-code-0010.swift
│ │ │ │ └── 02-03-TestingPresentation.tutorial
│ │ │ └── 04-NavigationStacks
│ │ │ │ ├── 02-04-01-code-0000.swift
│ │ │ │ ├── 02-04-01-code-0001.swift
│ │ │ │ ├── 02-04-01-code-0002.swift
│ │ │ │ ├── 02-04-01-code-0003.swift
│ │ │ │ ├── 02-04-01-code-0004.swift
│ │ │ │ ├── 02-04-01-code-0005.swift
│ │ │ │ ├── 02-04-01-code-0006.swift
│ │ │ │ ├── 02-04-01-code-0007.swift
│ │ │ │ ├── 02-04-02-code-0000-previous.swift
│ │ │ │ ├── 02-04-02-code-0000.swift
│ │ │ │ ├── 02-04-02-code-0001.swift
│ │ │ │ ├── 02-04-02-code-0002.swift
│ │ │ │ ├── 02-04-02-code-0003-previous.swift
│ │ │ │ ├── 02-04-02-code-0003.swift
│ │ │ │ ├── 02-04-02-code-0004.swift
│ │ │ │ ├── 02-04-02-code-0005-previous.swift
│ │ │ │ ├── 02-04-02-code-0005.swift
│ │ │ │ ├── 02-04-02-code-0006-previous.swift
│ │ │ │ ├── 02-04-02-code-0006.swift
│ │ │ │ ├── 02-04-03-code-0000-previous.swift
│ │ │ │ ├── 02-04-03-code-0000.swift
│ │ │ │ ├── 02-04-03-code-0001.swift
│ │ │ │ ├── 02-04-03-code-0002.swift
│ │ │ │ ├── 02-04-03-code-0003-previous.swift
│ │ │ │ ├── 02-04-03-code-0003.swift
│ │ │ │ ├── 02-04-03-code-0004-previous.swift
│ │ │ │ ├── 02-04-03-code-0004.swift
│ │ │ │ └── 02-04-NavigationStacks.tutorial
│ │ │ ├── MeetComposableArchitecture.tutorial
│ │ │ ├── chapter1.png
│ │ │ ├── chapter2.png
│ │ │ ├── chapter3.png
│ │ │ ├── chapter4.png
│ │ │ ├── chapter5.png
│ │ │ ├── chapter6.png
│ │ │ ├── chapter7.png
│ │ │ └── chapter8.png
│ ├── Effect.swift
│ ├── Effects
│ │ ├── Animation.swift
│ │ ├── Cancellation.swift
│ │ ├── Debounce.swift
│ │ ├── Publisher.swift
│ │ ├── TaskResult.swift
│ │ └── Throttle.swift
│ ├── Internal
│ │ ├── AreOrderedSetsDuplicates.swift
│ │ ├── AssumeIsolated.swift
│ │ ├── Box.swift
│ │ ├── Create.swift
│ │ ├── CurrentValueRelay.swift
│ │ ├── Debug.swift
│ │ ├── DefaultSubscript.swift
│ │ ├── Deprecations.swift
│ │ ├── DispatchQueue.swift
│ │ ├── EffectActions.swift
│ │ ├── EphemeralState.swift
│ │ ├── Exports.swift
│ │ ├── HashableStaticString.swift
│ │ ├── KeyPath+Sendable.swift
│ │ ├── Locking.swift
│ │ ├── Logger.swift
│ │ ├── NavigationID.swift
│ │ ├── NotificationName.swift
│ │ ├── OpenExistential.swift
│ │ ├── PresentationID.swift
│ │ ├── ReturningLastNonNilValue.swift
│ │ ├── RuntimeWarnings.swift
│ │ └── StackIDGenerator.swift
│ ├── Macros.swift
│ ├── Observation
│ │ ├── Alert+Observation.swift
│ │ ├── Binding+Observation.swift
│ │ ├── IdentifiedArray+Observation.swift
│ │ ├── NavigationStack+Observation.swift
│ │ ├── ObservableState.swift
│ │ ├── ObservationStateRegistrar.swift
│ │ ├── Store+Observation.swift
│ │ └── ViewAction.swift
│ ├── Reducer.swift
│ ├── Reducer
│ │ ├── ReducerBuilder.swift
│ │ └── Reducers
│ │ │ ├── BindingReducer.swift
│ │ │ ├── CombineReducers.swift
│ │ │ ├── DebugReducer.swift
│ │ │ ├── DependencyKeyWritingReducer.swift
│ │ │ ├── EmptyReducer.swift
│ │ │ ├── ForEachReducer.swift
│ │ │ ├── IfCaseLetReducer.swift
│ │ │ ├── IfLetReducer.swift
│ │ │ ├── OnChange.swift
│ │ │ ├── Optional.swift
│ │ │ ├── PresentationReducer.swift
│ │ │ ├── Reduce.swift
│ │ │ ├── Scope.swift
│ │ │ ├── SignpostReducer.swift
│ │ │ └── StackReducer.swift
│ ├── Resources
│ │ └── PrivacyInfo.xcprivacy
│ ├── Sharing
│ │ └── AppStorageKeyPathKey.swift
│ ├── Store.swift
│ ├── SwiftUI
│ │ ├── Alert.swift
│ │ ├── Binding.swift
│ │ ├── ConfirmationDialog.swift
│ │ ├── Deprecated
│ │ │ ├── ActionSheet.swift
│ │ │ ├── LegacyAlert.swift
│ │ │ └── NavigationLinkStore.swift
│ │ ├── ForEachStore.swift
│ │ ├── FullScreenCover.swift
│ │ ├── IfLetStore.swift
│ │ ├── NavigationDestination.swift
│ │ ├── NavigationStackStore.swift
│ │ ├── Popover.swift
│ │ ├── PresentationModifier.swift
│ │ ├── Sheet.swift
│ │ ├── SwitchStore.swift
│ │ └── WithViewStore.swift
│ ├── TestStore.swift
│ ├── UIKit
│ │ ├── AlertStateUIKit.swift
│ │ ├── IfLetUIKit.swift
│ │ └── NavigationStackControllerUIKit.swift
│ └── ViewStore.swift
└── ComposableArchitectureMacros
│ ├── Availability.swift
│ ├── Extensions.swift
│ ├── ObservableStateMacro.swift
│ ├── Plugins.swift
│ ├── PresentsMacro.swift
│ ├── ReducerMacro.swift
│ └── ViewActionMacro.swift
└── Tests
├── ComposableArchitectureMacrosTests
├── MacroBaseTestCase.swift
├── ObservableStateMacroTests.swift
├── PresentsMacroTests.swift
├── ReducerMacroTests.swift
└── ViewActionMacroTests.swift
└── ComposableArchitectureTests
├── BindableStoreTests.swift
├── BindingLocalTests.swift
├── CompatibilityTests.swift
├── ComposableArchitectureTests.swift
├── CurrentValueRelayTests.swift
├── DebugTests.swift
├── DependencyKeyWritingReducerTests.swift
├── EffectCancellationIsolationTests.swift
├── EffectCancellationTests.swift
├── EffectDebounceTests.swift
├── EffectFailureTests.swift
├── EffectOperationTests.swift
├── EffectRunTests.swift
├── EffectTests.swift
├── EnumReducerMacroTests.swift
├── Internal
├── BaseTCATestCase.swift
└── TestHelpers.swift
├── MacroConformanceTests.swift
├── MacroTests.swift
├── MemoryManagementTests.swift
├── ObservableStateEnumMacroTests.swift
├── ObservableTests.swift
├── ReducerBuilderTests.swift
├── ReducerTests.swift
├── Reducers
├── BindingReducerTests.swift
├── ForEachReducerTests.swift
├── IfCaseLetReducerTests.swift
├── IfLetReducerTests.swift
├── OnChangeReducerTests.swift
├── PresentationReducerTests.swift
└── StackReducerTests.swift
├── RuntimeWarningTests.swift
├── ScopeCacheTests.swift
├── ScopeLoggerTests.swift
├── ScopeTests.swift
├── StoreLifetimeTests.swift
├── StorePerceptionTests.swift
├── StoreTests.swift
├── TaskCancellationTests.swift
├── TaskResultTests.swift
├── TestStoreFailureTests.swift
├── TestStoreNonExhaustiveTests.swift
├── TestStoreTests.swift
├── ThrottleTests.swift
└── ViewStoreTests.swift
/.editorconfig:
--------------------------------------------------------------------------------
1 | # editorconfig.org
2 |
3 | root = true
4 |
5 | [*]
6 | indent_style = space
7 | indent_size = 2
8 | trim_trailing_whitespace = true
9 | insert_final_newline = true
10 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 | blank_issues_enabled: false
2 |
3 | contact_links:
4 | - name: Project Discussion
5 | url: https://github.com/pointfreeco/swift-composable-architecture/discussions
6 | about: Composable Architecture Q&A, ideas, and more
7 | - name: Documentation
8 | url: https://pointfreeco.github.io/swift-composable-architecture/main/documentation/composablearchitecture/
9 | about: Read the Composable Architecture's documentation
10 | - name: Videos
11 | url: https://www.pointfree.co/collections/composable-architecture
12 | about: Watch videos to get a behind-the-scenes look at how the Composable Architecture was motivated and built
13 | - name: Slack
14 | url: https://www.pointfree.co/slack-invite
15 | about: Community chat
16 |
--------------------------------------------------------------------------------
/.github/package.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.github/package.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.github/workflows/format.yml:
--------------------------------------------------------------------------------
1 | name: Format
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 |
8 | concurrency:
9 | group: format-${{ github.ref }}
10 | cancel-in-progress: true
11 |
12 | jobs:
13 | swift_format:
14 | name: swift-format
15 | runs-on: macos-15
16 | permissions:
17 | contents: write
18 | steps:
19 | - uses: actions/checkout@v4
20 | - name: Select Xcode 16.2
21 | run: sudo xcode-select -s /Applications/Xcode_16.2.app
22 | - name: Format
23 | run: make format
24 | - uses: stefanzweifel/git-auto-commit-action@v5
25 | with:
26 | commit_message: Run swift-format
27 | branch: 'main'
28 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | .build
3 | .swiftpm
4 | /Packages
5 | /*.swiftinterface
6 | /*.xcodeproj
7 | xcuserdata/
8 | .docc-build/
--------------------------------------------------------------------------------
/.spi.yml:
--------------------------------------------------------------------------------
1 | version: 1
2 | builder:
3 | configs:
4 | - platform: ios
5 | scheme: ComposableArchitecture
6 | - platform: macos-xcodebuild
7 | scheme: ComposableArchitecture
8 | - platform: tvos
9 | scheme: ComposableArchitecture
10 | - platform: watchos
11 | scheme: ComposableArchitecture
12 | - documentation_targets: [ComposableArchitecture]
13 |
--------------------------------------------------------------------------------
/ComposableArchitecture.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ComposableArchitecture.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Examples/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Examples/CaseStudies/CaseStudies.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Examples/CaseStudies/CaseStudies.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Examples/CaseStudies/README.md:
--------------------------------------------------------------------------------
1 | # Composable Architecture Case Studies
2 |
3 | This project includes a number of digestible examples of how to solve common problems using the Composable Architecture.
4 |
--------------------------------------------------------------------------------
/Examples/CaseStudies/SwiftUICaseStudies/Assets.xcassets/AppIcon.appiconset/AppIcon-60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Examples/CaseStudies/SwiftUICaseStudies/Assets.xcassets/AppIcon.appiconset/AppIcon-60@2x.png
--------------------------------------------------------------------------------
/Examples/CaseStudies/SwiftUICaseStudies/Assets.xcassets/AppIcon.appiconset/AppIcon-76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Examples/CaseStudies/SwiftUICaseStudies/Assets.xcassets/AppIcon.appiconset/AppIcon-76@2x.png
--------------------------------------------------------------------------------
/Examples/CaseStudies/SwiftUICaseStudies/Assets.xcassets/AppIcon.appiconset/AppIcon-iPadPro@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Examples/CaseStudies/SwiftUICaseStudies/Assets.xcassets/AppIcon.appiconset/AppIcon-iPadPro@2x.png
--------------------------------------------------------------------------------
/Examples/CaseStudies/SwiftUICaseStudies/Assets.xcassets/AppIcon.appiconset/AppIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Examples/CaseStudies/SwiftUICaseStudies/Assets.xcassets/AppIcon.appiconset/AppIcon.png
--------------------------------------------------------------------------------
/Examples/CaseStudies/SwiftUICaseStudies/Assets.xcassets/AppIcon.appiconset/transparent.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Examples/CaseStudies/SwiftUICaseStudies/Assets.xcassets/AppIcon.appiconset/transparent.png
--------------------------------------------------------------------------------
/Examples/CaseStudies/SwiftUICaseStudies/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Examples/CaseStudies/SwiftUICaseStudies/CaseStudiesApp.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 |
4 | @main
5 | struct CaseStudiesApp: App {
6 | var body: some Scene {
7 | WindowGroup {
8 | RootView()
9 | }
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/Examples/CaseStudies/SwiftUICaseStudies/Internal/AboutView.swift:
--------------------------------------------------------------------------------
1 | import SwiftUI
2 |
3 | struct AboutView: View {
4 | let readMe: String
5 |
6 | var body: some View {
7 | DisclosureGroup("About this case study") {
8 | Text(template: self.readMe)
9 | }
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/Examples/CaseStudies/SwiftUICaseStudies/Internal/CircularProgressView.swift:
--------------------------------------------------------------------------------
1 | import SwiftUI
2 |
3 | struct CircularProgressView: View {
4 | private let value: Double
5 |
6 | init(value: Double) {
7 | self.value = value
8 | }
9 |
10 | var body: some View {
11 | Circle()
12 | .trim(from: 0, to: CGFloat(self.value))
13 | .stroke(style: StrokeStyle(lineWidth: 2, lineCap: .round))
14 | .rotationEffect(.degrees(-90))
15 | .animation(.easeIn, value: self.value)
16 | }
17 | }
18 |
19 | #Preview {
20 | CircularProgressView(value: 0.3).frame(width: 44, height: 44)
21 | }
22 |
--------------------------------------------------------------------------------
/Examples/CaseStudies/SwiftUICaseStudies/Internal/UIViewRepresented.swift:
--------------------------------------------------------------------------------
1 | import SwiftUI
2 |
3 | struct UIViewRepresented: UIViewRepresentable {
4 | let makeUIView: (Context) -> UIViewType
5 | let updateUIView: (UIViewType, Context) -> Void = { _, _ in }
6 |
7 | func makeUIView(context: Context) -> UIViewType {
8 | self.makeUIView(context)
9 | }
10 |
11 | func updateUIView(_ uiView: UIViewType, context: Context) {
12 | self.updateUIView(uiView, context)
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/Examples/CaseStudies/UIKitCaseStudies/Assets.xcassets/AppIcon.appiconset/AppIcon-60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Examples/CaseStudies/UIKitCaseStudies/Assets.xcassets/AppIcon.appiconset/AppIcon-60@2x.png
--------------------------------------------------------------------------------
/Examples/CaseStudies/UIKitCaseStudies/Assets.xcassets/AppIcon.appiconset/AppIcon-76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Examples/CaseStudies/UIKitCaseStudies/Assets.xcassets/AppIcon.appiconset/AppIcon-76@2x.png
--------------------------------------------------------------------------------
/Examples/CaseStudies/UIKitCaseStudies/Assets.xcassets/AppIcon.appiconset/AppIcon-iPadPro@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Examples/CaseStudies/UIKitCaseStudies/Assets.xcassets/AppIcon.appiconset/AppIcon-iPadPro@2x.png
--------------------------------------------------------------------------------
/Examples/CaseStudies/UIKitCaseStudies/Assets.xcassets/AppIcon.appiconset/AppIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Examples/CaseStudies/UIKitCaseStudies/Assets.xcassets/AppIcon.appiconset/AppIcon.png
--------------------------------------------------------------------------------
/Examples/CaseStudies/UIKitCaseStudies/Assets.xcassets/AppIcon.appiconset/transparent.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Examples/CaseStudies/UIKitCaseStudies/Assets.xcassets/AppIcon.appiconset/transparent.png
--------------------------------------------------------------------------------
/Examples/CaseStudies/UIKitCaseStudies/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Examples/CaseStudies/UIKitCaseStudies/Internal/ActivityIndicatorViewController.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 |
3 | final class ActivityIndicatorViewController: UIViewController {
4 | override func viewDidLoad() {
5 | super.viewDidLoad()
6 |
7 | self.view.backgroundColor = .systemBackground
8 |
9 | let activityIndicator = UIActivityIndicatorView()
10 | activityIndicator.startAnimating()
11 | activityIndicator.translatesAutoresizingMaskIntoConstraints = false
12 | self.view.addSubview(activityIndicator)
13 |
14 | NSLayoutConstraint.activate([
15 | activityIndicator.centerXAnchor.constraint(
16 | equalTo: self.view.safeAreaLayoutGuide.centerXAnchor),
17 | activityIndicator.centerYAnchor.constraint(
18 | equalTo: self.view.safeAreaLayoutGuide.centerYAnchor),
19 | ])
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Examples/CaseStudies/UIKitCaseStudies/Preview Content/Preview Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Examples/CaseStudies/tvOSCaseStudies/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 | import UIKit
4 |
5 | @main
6 | final class AppDelegate: UIResponder, UIApplicationDelegate {
7 | var window: UIWindow?
8 |
9 | func application(
10 | _ application: UIApplication,
11 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
12 | ) -> Bool {
13 | let contentView = RootView(
14 | store: Store(initialState: Root.State()) {
15 | Root()
16 | }
17 | )
18 |
19 | let window = UIWindow(frame: UIScreen.main.bounds)
20 | window.rootViewController = UIHostingController(rootView: contentView)
21 | self.window = window
22 | window.makeKeyAndVisible()
23 | return true
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Examples/CaseStudies/tvOSCaseStudies/Assets.xcassets/AppIcon.appiconset/AppIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Examples/CaseStudies/tvOSCaseStudies/Assets.xcassets/AppIcon.appiconset/AppIcon.png
--------------------------------------------------------------------------------
/Examples/CaseStudies/tvOSCaseStudies/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Examples/CaseStudies/tvOSCaseStudies/Core.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 |
3 | @Reducer
4 | struct Root {
5 | struct State {
6 | var focus = Focus.State()
7 | }
8 |
9 | enum Action {
10 | case focus(Focus.Action)
11 | }
12 |
13 | var body: some Reducer {
14 | Scope(state: \.focus, action: \.focus) {
15 | Focus()
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/Examples/CaseStudies/tvOSCaseStudies/RootView.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 |
4 | struct RootView: View {
5 | let store: StoreOf
6 |
7 | var body: some View {
8 | NavigationView {
9 | Form {
10 | Section {
11 | FocusView(
12 | store: store.scope(state: \.focus, action: \.focus)
13 | )
14 | }
15 | }
16 | }
17 | }
18 | }
19 |
20 | #Preview {
21 | NavigationStack {
22 | RootView(
23 | store: Store(initialState: Root.State()) {
24 | Root()
25 | }
26 | )
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/Examples/Integration/Integration.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Examples/Integration/Integration.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Examples/Integration/Integration/Assets.xcassets/AccentColor.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "idiom" : "universal"
5 | }
6 | ],
7 | "info" : {
8 | "author" : "xcode",
9 | "version" : 1
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/Examples/Integration/Integration/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "platform" : "ios",
6 | "size" : "1024x1024"
7 | }
8 | ],
9 | "info" : {
10 | "author" : "xcode",
11 | "version" : 1
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/Examples/Integration/Integration/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Examples/Integration/Integration/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleURLTypes
6 |
7 |
8 | CFBundleTypeRole
9 | Editor
10 | CFBundleURLIconFile
11 |
12 | CFBundleURLName
13 |
14 | CFBundleURLSchemes
15 |
16 | integration
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/Examples/Integration/Integration/Preview Content/Preview Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Examples/Integration/IntegrationUITests/Internal/TestHelpers.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 |
3 | @available(
4 | *,
5 | deprecated,
6 | message: "This is a test that currently fails but should not in the future."
7 | )
8 | func XCTTODO(_ message: String) {
9 | XCTExpectFailure(message)
10 | }
11 |
12 | extension XCUIElement {
13 | func find(
14 | timeout: TimeInterval = 0.3,
15 | filePath: StaticString = #filePath,
16 | line: UInt = #line
17 | ) -> XCUIElement {
18 | if !self.waitForExistence(timeout: timeout) {
19 | XCTFail("Failed to find \(self).", file: filePath, line: line)
20 | }
21 | return self
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Examples/Integration/IntegrationUITests/Test Cases/MultipleAlertsTests.swift:
--------------------------------------------------------------------------------
1 | import TestCases
2 | import XCTest
3 |
4 | final class MultipleAlertsTests: BaseIntegrationTests {
5 | @MainActor
6 | override func setUpWithError() throws {
7 | try XCTSkipIf(ProcessInfo.processInfo.environment["CI"] != nil)
8 | try super.setUpWithError()
9 | self.app.buttons["Test cases"].tap()
10 | app.collectionViews.buttons[TestCase.Cases.multipleAlerts.rawValue].tap()
11 | }
12 |
13 | @MainActor
14 | func testMultipleAlerts() {
15 | app.buttons["Show alert"].tap()
16 |
17 | app.buttons["Another!"].tap()
18 |
19 | app.buttons["I'm done"].tap()
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Examples/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version:5.2
2 |
3 | import PackageDescription
4 |
5 | let package = Package(
6 | name: "Examples",
7 | products: [],
8 | targets: []
9 | )
10 |
--------------------------------------------------------------------------------
/Examples/Search/Search.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Examples/Search/Search.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Examples/Search/Search/Assets.xcassets/AppIcon.appiconset/AppIcon-60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Examples/Search/Search/Assets.xcassets/AppIcon.appiconset/AppIcon-60@2x.png
--------------------------------------------------------------------------------
/Examples/Search/Search/Assets.xcassets/AppIcon.appiconset/AppIcon-76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Examples/Search/Search/Assets.xcassets/AppIcon.appiconset/AppIcon-76@2x.png
--------------------------------------------------------------------------------
/Examples/Search/Search/Assets.xcassets/AppIcon.appiconset/AppIcon-iPadPro@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Examples/Search/Search/Assets.xcassets/AppIcon.appiconset/AppIcon-iPadPro@2x.png
--------------------------------------------------------------------------------
/Examples/Search/Search/Assets.xcassets/AppIcon.appiconset/AppIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Examples/Search/Search/Assets.xcassets/AppIcon.appiconset/AppIcon.png
--------------------------------------------------------------------------------
/Examples/Search/Search/Assets.xcassets/AppIcon.appiconset/transparent.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Examples/Search/Search/Assets.xcassets/AppIcon.appiconset/transparent.png
--------------------------------------------------------------------------------
/Examples/Search/Search/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Examples/Search/Search/SearchApp.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 |
4 | @main
5 | struct SearchApp: App {
6 | static let store = Store(initialState: Search.State()) {
7 | Search()
8 | ._printChanges()
9 | }
10 |
11 | var body: some Scene {
12 | WindowGroup {
13 | SearchView(store: Self.store)
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Examples/SpeechRecognition/README.md:
--------------------------------------------------------------------------------
1 | # Speech Recognition
2 |
3 | This application demonstrates how to work with a complex dependency in the Composable Architecture. It uses the `SFSpeechRecognizer` API from the `Speech` framework to listen to audio on the device and live-transcribe it to the UI.
4 |
5 | The `SFSpeechRecognizer` class is a complex dependency, and if we used it freely in our application we wouldn't be able to test any of that code. So, instead, we wrap the API in a `SpeechClient` type that exposes asynchronous endpoints for accessing the underlying `SFSpeechRecognizer` class. Then we can use it in the reducer in an understandable way, _and_ we can write tests for the reducer.
6 |
--------------------------------------------------------------------------------
/Examples/SpeechRecognition/SpeechRecognition/Assets.xcassets/AppIcon.appiconset/AppIcon-60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Examples/SpeechRecognition/SpeechRecognition/Assets.xcassets/AppIcon.appiconset/AppIcon-60@2x.png
--------------------------------------------------------------------------------
/Examples/SpeechRecognition/SpeechRecognition/Assets.xcassets/AppIcon.appiconset/AppIcon-76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Examples/SpeechRecognition/SpeechRecognition/Assets.xcassets/AppIcon.appiconset/AppIcon-76@2x.png
--------------------------------------------------------------------------------
/Examples/SpeechRecognition/SpeechRecognition/Assets.xcassets/AppIcon.appiconset/AppIcon-iPadPro@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Examples/SpeechRecognition/SpeechRecognition/Assets.xcassets/AppIcon.appiconset/AppIcon-iPadPro@2x.png
--------------------------------------------------------------------------------
/Examples/SpeechRecognition/SpeechRecognition/Assets.xcassets/AppIcon.appiconset/AppIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Examples/SpeechRecognition/SpeechRecognition/Assets.xcassets/AppIcon.appiconset/AppIcon.png
--------------------------------------------------------------------------------
/Examples/SpeechRecognition/SpeechRecognition/Assets.xcassets/AppIcon.appiconset/transparent.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Examples/SpeechRecognition/SpeechRecognition/Assets.xcassets/AppIcon.appiconset/transparent.png
--------------------------------------------------------------------------------
/Examples/SpeechRecognition/SpeechRecognition/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Examples/SpeechRecognition/SpeechRecognition/SpeechRecognitionApp.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 |
4 | @main
5 | struct SpeechRecognitionApp: App {
6 | static let store = Store(initialState: SpeechRecognition.State()) {
7 | SpeechRecognition()
8 | ._printChanges()
9 | }
10 |
11 | var body: some Scene {
12 | WindowGroup {
13 | SpeechRecognitionView(store: Self.store)
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Examples/SyncUps/SyncUps/Assets.xcassets/AccentColor.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "idiom" : "universal"
5 | }
6 | ],
7 | "info" : {
8 | "author" : "xcode",
9 | "version" : 1
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/Examples/SyncUps/SyncUps/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "platform" : "ios",
6 | "size" : "1024x1024"
7 | }
8 | ],
9 | "info" : {
10 | "author" : "xcode",
11 | "version" : 1
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/Examples/SyncUps/SyncUps/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Examples/SyncUps/SyncUps/Assets.xcassets/Themes/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Examples/SyncUps/SyncUps/Dependencies/OpenSettings.swift:
--------------------------------------------------------------------------------
1 | import Dependencies
2 | import UIKit
3 |
4 | extension DependencyValues {
5 | var openSettings: @Sendable () async -> Void {
6 | get { self[OpenSettingsKey.self] }
7 | set { self[OpenSettingsKey.self] = newValue }
8 | }
9 |
10 | private enum OpenSettingsKey: DependencyKey {
11 | typealias Value = @Sendable () async -> Void
12 |
13 | static let liveValue: @Sendable () async -> Void = {
14 | await MainActor.run {
15 | UIApplication.shared.open(URL(string: UIApplication.openSettingsURLString)!)
16 | }
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/Examples/SyncUps/SyncUps/Meeting.swift:
--------------------------------------------------------------------------------
1 | import SwiftUI
2 |
3 | struct MeetingView: View {
4 | let meeting: Meeting
5 | let syncUp: SyncUp
6 |
7 | var body: some View {
8 | Form {
9 | Section {
10 | ForEach(syncUp.attendees) { attendee in
11 | Text(attendee.name)
12 | }
13 | } header: {
14 | Text("Attendees")
15 | }
16 | Section {
17 | Text(meeting.transcript)
18 | } header: {
19 | Text("Transcript")
20 | }
21 | }
22 | .navigationTitle(Text(meeting.date, style: .date))
23 | }
24 | }
25 |
26 | #Preview {
27 | MeetingView(meeting: SyncUp.mock.meetings[0], syncUp: .mock)
28 | }
29 |
--------------------------------------------------------------------------------
/Examples/SyncUps/SyncUps/Resources/ding.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Examples/SyncUps/SyncUps/Resources/ding.wav
--------------------------------------------------------------------------------
/Examples/TicTacToe/App/Assets.xcassets/AppIcon.appiconset/AppIcon-60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Examples/TicTacToe/App/Assets.xcassets/AppIcon.appiconset/AppIcon-60@2x.png
--------------------------------------------------------------------------------
/Examples/TicTacToe/App/Assets.xcassets/AppIcon.appiconset/AppIcon-76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Examples/TicTacToe/App/Assets.xcassets/AppIcon.appiconset/AppIcon-76@2x.png
--------------------------------------------------------------------------------
/Examples/TicTacToe/App/Assets.xcassets/AppIcon.appiconset/AppIcon-iPadPro@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Examples/TicTacToe/App/Assets.xcassets/AppIcon.appiconset/AppIcon-iPadPro@2x.png
--------------------------------------------------------------------------------
/Examples/TicTacToe/App/Assets.xcassets/AppIcon.appiconset/AppIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Examples/TicTacToe/App/Assets.xcassets/AppIcon.appiconset/AppIcon.png
--------------------------------------------------------------------------------
/Examples/TicTacToe/App/Assets.xcassets/AppIcon.appiconset/transparent.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Examples/TicTacToe/App/Assets.xcassets/AppIcon.appiconset/transparent.png
--------------------------------------------------------------------------------
/Examples/TicTacToe/App/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Examples/TicTacToe/App/TicTacToeApp.swift:
--------------------------------------------------------------------------------
1 | import SwiftUI
2 |
3 | @main
4 | struct TicTacToeApp: App {
5 | var body: some Scene {
6 | WindowGroup {
7 | RootView()
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/Examples/TicTacToe/TicTacToe.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Examples/TicTacToe/TicTacToe.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Examples/TicTacToe/tic-tac-toe/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | /.build
3 | /Packages
4 | /*.xcodeproj
5 | xcuserdata/
6 | DerivedData/
7 | .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
8 |
--------------------------------------------------------------------------------
/Examples/TicTacToe/tic-tac-toe/Sources/AppSwiftUI/AppView.swift:
--------------------------------------------------------------------------------
1 | import AppCore
2 | import ComposableArchitecture
3 | import LoginSwiftUI
4 | import NewGameSwiftUI
5 | import SwiftUI
6 |
7 | public struct AppView: View {
8 | let store: StoreOf
9 |
10 | public init(store: StoreOf) {
11 | self.store = store
12 | }
13 |
14 | public var body: some View {
15 | switch store.case {
16 | case let .login(store):
17 | NavigationStack {
18 | LoginView(store: store)
19 | }
20 | case let .newGame(store):
21 | NavigationStack {
22 | NewGameView(store: store)
23 | }
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Examples/Todos/README.md:
--------------------------------------------------------------------------------
1 | # Todos
2 |
3 | This simple todo application built with the Composable Architecture includes a few bells and whistles:
4 |
5 | * Filtering and rearranging todo items.
6 | * Automatically sort completed todos to the bottom of the list.
7 | * Debouncing the sort action to allow multiple todo items to be toggled before being sorted.
8 | * A comprehensive test suite.
9 |
--------------------------------------------------------------------------------
/Examples/Todos/Todos.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Examples/Todos/Todos.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Examples/Todos/Todos/Assets.xcassets/AppIcon.appiconset/AppIcon-60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Examples/Todos/Todos/Assets.xcassets/AppIcon.appiconset/AppIcon-60@2x.png
--------------------------------------------------------------------------------
/Examples/Todos/Todos/Assets.xcassets/AppIcon.appiconset/AppIcon-76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Examples/Todos/Todos/Assets.xcassets/AppIcon.appiconset/AppIcon-76@2x.png
--------------------------------------------------------------------------------
/Examples/Todos/Todos/Assets.xcassets/AppIcon.appiconset/AppIcon-iPadPro@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Examples/Todos/Todos/Assets.xcassets/AppIcon.appiconset/AppIcon-iPadPro@2x.png
--------------------------------------------------------------------------------
/Examples/Todos/Todos/Assets.xcassets/AppIcon.appiconset/AppIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Examples/Todos/Todos/Assets.xcassets/AppIcon.appiconset/AppIcon.png
--------------------------------------------------------------------------------
/Examples/Todos/Todos/Assets.xcassets/AppIcon.appiconset/transparent.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Examples/Todos/Todos/Assets.xcassets/AppIcon.appiconset/transparent.png
--------------------------------------------------------------------------------
/Examples/Todos/Todos/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Examples/Todos/Todos/TodosApp.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 |
4 | @main
5 | struct TodosApp: App {
6 | static let store = Store(initialState: Todos.State()) {
7 | Todos()
8 | ._printChanges()
9 | }
10 |
11 | var body: some Scene {
12 | WindowGroup {
13 | AppView(store: Self.store)
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Examples/VoiceMemos/README.md:
--------------------------------------------------------------------------------
1 | # Voice Memos
2 |
3 | This application demonstrates how to work with multiple dependencies and manage a complex state machine driven off of timers in the Composable Architecture. Some functionality includes:
4 |
5 | * Requesting the user’s permission to record audio.
6 | * Prompting the user if insufficient permission is provided.
7 | * Audio recording and playback.
8 | * Handling errors that may occur during recording or playback.
9 | * Stubbing dependencies to work with SwiftUI previews.
10 |
--------------------------------------------------------------------------------
/Examples/VoiceMemos/VoiceMemos.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Examples/VoiceMemos/VoiceMemos.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Examples/VoiceMemos/VoiceMemos/Assets.xcassets/AppIcon.appiconset/AppIcon-60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Examples/VoiceMemos/VoiceMemos/Assets.xcassets/AppIcon.appiconset/AppIcon-60@2x.png
--------------------------------------------------------------------------------
/Examples/VoiceMemos/VoiceMemos/Assets.xcassets/AppIcon.appiconset/AppIcon-76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Examples/VoiceMemos/VoiceMemos/Assets.xcassets/AppIcon.appiconset/AppIcon-76@2x.png
--------------------------------------------------------------------------------
/Examples/VoiceMemos/VoiceMemos/Assets.xcassets/AppIcon.appiconset/AppIcon-iPadPro@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Examples/VoiceMemos/VoiceMemos/Assets.xcassets/AppIcon.appiconset/AppIcon-iPadPro@2x.png
--------------------------------------------------------------------------------
/Examples/VoiceMemos/VoiceMemos/Assets.xcassets/AppIcon.appiconset/AppIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Examples/VoiceMemos/VoiceMemos/Assets.xcassets/AppIcon.appiconset/AppIcon.png
--------------------------------------------------------------------------------
/Examples/VoiceMemos/VoiceMemos/Assets.xcassets/AppIcon.appiconset/transparent.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Examples/VoiceMemos/VoiceMemos/Assets.xcassets/AppIcon.appiconset/transparent.png
--------------------------------------------------------------------------------
/Examples/VoiceMemos/VoiceMemos/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Examples/VoiceMemos/VoiceMemos/AudioPlayerClient/AudioPlayerClient.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Foundation
3 |
4 | @DependencyClient
5 | struct AudioPlayerClient {
6 | var play: @Sendable (_ url: URL) async throws -> Bool
7 | }
8 |
9 | extension AudioPlayerClient: TestDependencyKey {
10 | static let previewValue = Self(
11 | play: { _ in
12 | try await Task.sleep(for: .seconds(5))
13 | return true
14 | }
15 | )
16 |
17 | static let testValue = Self()
18 | }
19 |
20 | extension DependencyValues {
21 | var audioPlayer: AudioPlayerClient {
22 | get { self[AudioPlayerClient.self] }
23 | set { self[AudioPlayerClient.self] = newValue }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Examples/VoiceMemos/VoiceMemos/Helpers.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | let dateComponentsFormatter: DateComponentsFormatter = {
4 | let formatter = DateComponentsFormatter()
5 | formatter.allowedUnits = [.minute, .second]
6 | formatter.zeroFormattingBehavior = .pad
7 | return formatter
8 | }()
9 |
--------------------------------------------------------------------------------
/Examples/VoiceMemos/VoiceMemos/VoiceMemosApp.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 |
4 | @main
5 | struct VoiceMemosApp: App {
6 | static let store = Store(initialState: VoiceMemos.State()) {
7 | VoiceMemos()
8 | ._printChanges()
9 | }
10 |
11 | var body: some Scene {
12 | WindowGroup {
13 | VoiceMemosView(store: Self.store)
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Dependencies/IsPresented.swift:
--------------------------------------------------------------------------------
1 | extension DependencyValues {
2 | /// A Boolean value that indicates whether the current feature is being presented from a parent
3 | /// feature.
4 | ///
5 | /// This value is set to true on reducers that are run from within
6 | /// ``Reducer/ifLet(_:action:destination:fileID:filePath:line:column:)-4ub6q`` and
7 | /// ``Reducer/forEach(_:action:destination:fileID:filePath:line:column:)-9svqb``.
8 | ///
9 | /// See ``DismissEffect`` for more information on how child features can easily dismiss themselves
10 | /// without communicating to the parent.
11 | public var isPresented: Bool {
12 | self.dismiss.dismiss != nil
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Extensions/Action.md:
--------------------------------------------------------------------------------
1 | # ``ComposableArchitecture/Reducer/Action``
2 |
3 | ## Topics
4 |
5 | ### View actions
6 |
7 | - ``ViewAction``
8 | - ``ViewAction(for:)``
9 | - ``ViewActionSending``
10 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Extensions/Deprecations/ScopeDeprecations.md:
--------------------------------------------------------------------------------
1 | # Deprecations
2 |
3 | Review unsupported reducer APIs and their replacements.
4 |
5 | ## Overview
6 |
7 | Avoid using deprecated APIs in your app. Select a method to see the replacement that you should use
8 | instead.
9 |
10 | ## Topics
11 |
12 | ### Case path deprecations
13 |
14 | - ``Scope/init(state:action:child:)-2srhu``
15 | - ``Scope/init(state:action:child:fileID:filePath:line:column:)-8j92g``
16 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Extensions/Deprecations/StoreDeprecations.md:
--------------------------------------------------------------------------------
1 | # Deprecations
2 |
3 | Review unsupported store APIs and their replacements.
4 |
5 | ## Overview
6 |
7 | Avoid using deprecated APIs in your app. Select a method to see the replacement that you should use
8 | instead.
9 |
10 | ## Topics
11 |
12 | ### Scoping stores
13 |
14 | - ``Store/scope(state:action:)-9iai9``
15 |
16 | ### UIKit integration
17 |
18 | - ``Store/ifLet(then:else:)``
19 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Extensions/EffectRun.md:
--------------------------------------------------------------------------------
1 | # ``ComposableArchitecture/Effect/run(priority:operation:catch:fileID:filePath:line:column:)``
2 |
3 | ## Topics
4 |
5 | ### Sending actions
6 |
7 | - ``Send``
8 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Extensions/EffectSend.md:
--------------------------------------------------------------------------------
1 | # ``ComposableArchitecture/Effect/send(_:)``
2 |
3 | ## Topics
4 |
5 | ### Animating actions
6 |
7 | - ``Effect/send(_:animation:)``
8 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Extensions/IdentifiedAction.md:
--------------------------------------------------------------------------------
1 | # ``ComposableArchitecture/IdentifiedAction``
2 |
3 | ## Topics
4 |
5 | ### Supporting types
6 |
7 | - ``IdentifiedActionOf``
8 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Extensions/NavigationLinkState.md:
--------------------------------------------------------------------------------
1 | # ``SwiftUI/NavigationLink/init(state:label:fileID:filePath:line:column:)``
2 |
3 | ## Topics
4 |
5 | ### Overloads
6 |
7 | - ``SwiftUI/NavigationLink/init(_:state:fileID:line:)-1fmz8``
8 | - ``SwiftUI/NavigationLink/init(_:state:fileID:line:)-3xjq3``
9 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Extensions/ObservableState.md:
--------------------------------------------------------------------------------
1 | # ``ComposableArchitecture/ObservableState()``
2 |
3 | ## Topics
4 |
5 | ### Conformance
6 |
7 | - ``ObservableState``
8 |
9 | ### Change tracking
10 |
11 | - ``ObservableStateID``
12 | - ``ObservationStateRegistrar``
13 |
14 | ### Supporting macros
15 |
16 | - ``ObservationStateTracked()``
17 | - ``ObservationStateIgnored()``
18 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Extensions/Presents.md:
--------------------------------------------------------------------------------
1 | # ``ComposableArchitecture/Presents()``
2 |
3 | ## Topics
4 |
5 | ### Property wrapper
6 |
7 | - ``PresentationState``
8 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Extensions/Reduce.md:
--------------------------------------------------------------------------------
1 | # ``ComposableArchitecture/Reduce``
2 |
3 | ## Topics
4 |
5 | ### Creating a reducer
6 |
7 | - ``init(_:)-6xl6k``
8 |
9 | ### Type erased reducers
10 |
11 | - ``init(_:)-9kwa6``
12 |
13 | ### Reduce conformance
14 |
15 | - ``Reducer/body-20w8t``
16 | - ``Reducer/reduce(into:action:)-1t2ri``
17 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Extensions/ReducerBody.md:
--------------------------------------------------------------------------------
1 | # ``ComposableArchitecture/Reducer/body-swift.property``
2 |
3 | ## Topics
4 |
5 | ### Associated type
6 |
7 | - ``Body``
8 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Extensions/ReducerBuilder.md:
--------------------------------------------------------------------------------
1 | # ``ComposableArchitecture/ReducerBuilder``
2 |
3 | ## Topics
4 |
5 | ### Building reducers
6 |
7 | - ``buildExpression(_:)-cp3q``
8 | - ``buildExpression(_:)-9uxku``
9 | - ``buildBlock(_:)``
10 | - ``buildBlock()``
11 | - ``buildPartialBlock(first:)``
12 | - ``buildPartialBlock(accumulated:next:)``
13 | - ``buildOptional(_:)``
14 | - ``buildEither(first:)``
15 | - ``buildEither(second:)``
16 | - ``buildArray(_:)``
17 | - ``buildLimitedAvailability(_:)``
18 | - ``buildFinalResult(_:)``
19 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Extensions/ReducerForEach.md:
--------------------------------------------------------------------------------
1 | # ``ComposableArchitecture/Reducer/forEach(_:action:element:fileID:filePath:line:column:)-6zye8``
2 |
3 | ## Topics
4 |
5 | ### Identifying actions
6 |
7 | - ``IdentifiedAction``
8 |
9 | ### Navigation stacks
10 |
11 | - ``StackState``
12 | - ``StackAction``
13 | - ``StackActionOf``
14 | - ``Reducer/forEach(_:action:destination:fileID:filePath:line:column:)-9svqb``
15 | - ``Reducer/forEach(_:action:)``
16 | - ``DismissEffect``
17 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Extensions/ReducerMacro.md:
--------------------------------------------------------------------------------
1 | # ``ComposableArchitecture/Reducer()``
2 |
3 | ## Topics
4 |
5 | ### Enum reducers
6 |
7 | - ``Reducer(state:action:)``
8 | - ``ReducerCaseEphemeral()``
9 | - ``ReducerCaseIgnored()``
10 | - ``CaseReducer``
11 | - ``CaseReducerState``
12 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Extensions/ReducerlIfLet.md:
--------------------------------------------------------------------------------
1 | # ``ComposableArchitecture/Reducer/ifLet(_:action:then:fileID:filePath:line:column:)-2r2pn``
2 |
3 | ## Topics
4 |
5 | ### Enum state
6 |
7 | - ``Reducer/ifLet(_:action:)``
8 |
9 | ### Ephemeral state
10 |
11 | - ``Reducer/ifLet(_:action:fileID:filePath:line:column:)-5bebx``
12 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Extensions/ReducerlIfLetPresentation.md:
--------------------------------------------------------------------------------
1 | # ``ComposableArchitecture/Reducer/ifLet(_:action:destination:fileID:filePath:line:column:)-4ub6q``
2 |
3 | ## Topics
4 |
5 | ### Ephemeral state
6 |
7 | - ``Reducer/ifLet(_:action:fileID:filePath:line:column:)-3ux09``
8 |
9 | ### Presentation
10 |
11 | - ``PresentationState``
12 | - ``PresentationAction``
13 | - ``DismissEffect``
14 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Extensions/Scope.md:
--------------------------------------------------------------------------------
1 | # ``ComposableArchitecture/Scope``
2 |
3 | ## Topics
4 |
5 | ### Struct state
6 |
7 | - ``init(state:action:child:)-88vdx``
8 |
9 | ### Enum state
10 |
11 | - ``init(state:action:child:fileID:filePath:line:column:)-9g44g``
12 |
13 | ### Deprecations
14 |
15 | -
16 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Extensions/State.md:
--------------------------------------------------------------------------------
1 | # ``ComposableArchitecture/Reducer/State``
2 |
3 | ## Topics
4 |
5 | ### Observing state
6 |
7 | - ``ObservableState()``
8 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Extensions/StoreDynamicMemberLookup.md:
--------------------------------------------------------------------------------
1 | # ``ComposableArchitecture/Store/subscript(dynamicMember:)-655ef``
2 |
3 | ## Topics
4 |
5 | ### Writable, bindable state
6 |
7 | - ``Store/subscript(dynamicMember:)-6ilk2``
8 | - ``Store/subscript(dynamicMember:)-85nex``
9 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Extensions/StoreState.md:
--------------------------------------------------------------------------------
1 | # ``ComposableArchitecture/Store/state-1qxwl``
2 |
3 | ## Topics
4 |
5 | ### Writable, bindable state
6 |
7 | - ``Store/state-20w4g``
8 | - ``Store/state-2wgiw``
9 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Extensions/SwiftUIBinding.md:
--------------------------------------------------------------------------------
1 | # ``SwiftUI/Binding``
2 |
3 | Learn how SwiftUI's `Binding` type has been extended for the Composable Architecture
4 |
5 | ## Overview
6 |
7 | A binding to a ``Store``is extended with several unique scoping operations that can be used to power
8 | controls and drive navigation.
9 |
10 | ## Topics
11 |
12 | ### Control bindings
13 |
14 | - ``SwiftUI/Binding/subscript(dynamicMember:)``
15 |
16 | ### Navigation bindings
17 |
18 | - ``SwiftUI/Binding/scope(state:action:fileID:filePath:line:column:)``
19 | - ``SwiftUI/Binding/scope(state:action:)-35r82``
20 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Extensions/SwiftUIBindingScopeForEach.md:
--------------------------------------------------------------------------------
1 | # ``SwiftUI/Binding/scope(state:action:)-35r82``
2 |
3 | ## Topics
4 |
5 | ### Bindable
6 |
7 | - ``SwiftUI/Bindable/scope(state:action:)``
8 | - ``Perception/Bindable/scope(state:action:)``
9 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Extensions/SwiftUIBindingScopeIfLet.md:
--------------------------------------------------------------------------------
1 | # ``SwiftUI/Binding/scope(state:action:fileID:filePath:line:column:)``
2 |
3 | ## Topics
4 |
5 | ### Bindable
6 |
7 | - ``SwiftUI/Bindable/scope(state:action:fileID:line:)``
8 | - ``Perception/Bindable/scope(state:action:fileID:line:)``
9 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Extensions/SwiftUIBindingSubscript.md:
--------------------------------------------------------------------------------
1 | # ``SwiftUI/Binding/subscript(dynamicMember:)``
2 |
3 | ## Topics
4 |
5 | ### Bindable
6 |
7 | - ``SwiftUI/Bindable/subscript(dynamicMember:)``
8 | - ``Perception/Bindable/subscript(dynamicMember:)``
9 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Extensions/SwitchStore.md:
--------------------------------------------------------------------------------
1 | # ``ComposableArchitecture/SwitchStore``
2 |
3 | ## Topics
4 |
5 | ### Building Content
6 |
7 | - ``CaseLet``
8 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Extensions/TaskResult.md:
--------------------------------------------------------------------------------
1 | # ``ComposableArchitecture/TaskResult``
2 |
3 | ## Topics
4 |
5 | ### Representing a task result
6 |
7 | - ``success(_:)``
8 | - ``failure(_:)``
9 |
10 | ### Converting a throwing expression
11 |
12 | - ``init(catching:)``
13 |
14 | ### Accessing a result's value
15 |
16 | - ``value``
17 |
18 | ### Transforming results
19 |
20 | - ``map(_:)``
21 | - ``flatMap(_:)``
22 | - ``init(_:)``
23 | - ``Swift/Result/init(_:)``
24 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Extensions/TestStoreDependencies.md:
--------------------------------------------------------------------------------
1 | # ``ComposableArchitecture/TestStore/dependencies``
2 |
3 | ## Topics
4 |
5 | ### Configuring exhaustivity
6 |
7 | - ``withDependencies(_:operation:)-988rh``
8 | - ``withDependencies(_:operation:)-61in2``
9 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Extensions/TestStoreExhaustivity.md:
--------------------------------------------------------------------------------
1 | # ``ComposableArchitecture/TestStore/exhaustivity``
2 |
3 | ## Topics
4 |
5 | ### Configuring exhaustivity
6 |
7 | - ``Exhaustivity``
8 | - ``withExhaustivity(_:operation:)-3fqeg``
9 | - ``withExhaustivity(_:operation:)-1mhu4``
10 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Extensions/ViewStoreBinding.md:
--------------------------------------------------------------------------------
1 | # ``ComposableArchitecture/ViewStore/binding(get:send:)-65xes``
2 |
3 | ## Topics
4 |
5 | ### Overloads
6 |
7 | - ``binding(get:send:)-l66r``
8 | - ``binding(send:)-7nwak``
9 | - ``binding(send:)-705m7``
10 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Extensions/WithViewStore.md:
--------------------------------------------------------------------------------
1 | # ``ComposableArchitecture/WithViewStore``
2 |
3 | ## Overview
4 |
5 | ## Topics
6 |
7 | ### Creating a view
8 |
9 | - ``init(_:observe:content:file:line:)-8g15l``
10 |
11 | ### Debugging view updates
12 |
13 | - ``_printChanges(_:)``
14 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Extensions/WithViewStoreInit.md:
--------------------------------------------------------------------------------
1 | # ``ComposableArchitecture/WithViewStore/init(_:observe:content:file:line:)-8g15l``
2 |
3 | ## Topics
4 |
5 | ### Overloads
6 |
7 | - ``WithViewStore/init(_:observe:removeDuplicates:content:file:line:)-7y5bp``
8 | - ``WithViewStore/init(_:observe:send:content:file:line:)-5d0z5``
9 | - ``WithViewStore/init(_:observe:send:removeDuplicates:content:file:line:)-dheh``
10 |
11 | ### Bindings
12 |
13 | - ``WithViewStore/init(_:observe:content:file:line:)-4gpoj``
14 | - ``WithViewStore/init(_:observe:removeDuplicates:content:file:line:)-1zbzi``
15 | - ``WithViewStore/init(_:observe:send:content:file:line:)-3r7aq``
16 | - ``WithViewStore/init(_:observe:send:removeDuplicates:content:file:line:)-4izbr``
17 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Resources/01-02-image-0003.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Sources/ComposableArchitecture/Documentation.docc/Resources/01-02-image-0003.png
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Resources/01-02-video-0005.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Sources/ComposableArchitecture/Documentation.docc/Resources/01-02-video-0005.mp4
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Resources/01-02-video-0006.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Sources/ComposableArchitecture/Documentation.docc/Resources/01-02-video-0006.mp4
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Resources/01-03-image-0005.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Sources/ComposableArchitecture/Documentation.docc/Resources/01-03-image-0005.jpg
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Resources/01-homepage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Sources/ComposableArchitecture/Documentation.docc/Resources/01-homepage.png
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Resources/02-01-image-0001.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Sources/ComposableArchitecture/Documentation.docc/Resources/02-01-image-0001.png
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Resources/02-02-video-0005.mov:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Sources/ComposableArchitecture/Documentation.docc/Resources/02-02-video-0005.mov
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Resources/02-homepage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Sources/ComposableArchitecture/Documentation.docc/Resources/02-homepage.png
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Resources/03-03-video-0006.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Sources/ComposableArchitecture/Documentation.docc/Resources/03-03-video-0006.mp4
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Resources/ch02-sub01-sec01-image-0001.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Sources/ComposableArchitecture/Documentation.docc/Resources/ch02-sub01-sec01-image-0001.png
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Resources/ch02-sub01-sec01-image-0002.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Sources/ComposableArchitecture/Documentation.docc/Resources/ch02-sub01-sec01-image-0002.png
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Resources/ch02-sub01-sec03-image-0000.mov:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Sources/ComposableArchitecture/Documentation.docc/Resources/ch02-sub01-sec03-image-0000.mov
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Resources/ch02-sub02-sec01-0000.mov:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Sources/ComposableArchitecture/Documentation.docc/Resources/ch02-sub02-sec01-0000.mov
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Resources/ch02-sub04-sec01-image-0000.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Sources/ComposableArchitecture/Documentation.docc/Resources/ch02-sub04-sec01-image-0000.png
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Resources/ch02-sub04-sec01-video-0000.mov:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Sources/ComposableArchitecture/Documentation.docc/Resources/ch02-sub04-sec01-video-0000.mov
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Resources/ch02-sub04-sec03-video-0000.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Sources/ComposableArchitecture/Documentation.docc/Resources/ch02-sub04-sec03-video-0000.mp4
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/01-WhatIsSyncUps/CreateProject-0001-image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/01-WhatIsSyncUps/CreateProject-0001-image.png
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/01-WhatIsSyncUps/CreateProject-0002-image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/01-WhatIsSyncUps/CreateProject-0002-image.png
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/01-WhatIsSyncUps/CreateProject-0003-image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/01-WhatIsSyncUps/CreateProject-0003-image.png
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/01-WhatIsSyncUps/CreateProject-0004-image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/01-WhatIsSyncUps/CreateProject-0004-image.png
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/01-WhatIsSyncUps/TourOfSyncUps-0003-image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/01-WhatIsSyncUps/TourOfSyncUps-0003-image.png
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/01-WhatIsSyncUps/TourOfSyncUps-0004-image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/01-WhatIsSyncUps/TourOfSyncUps-0004-image.png
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/01-WhatIsSyncUps/TourOfSyncUps-0005-image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/01-WhatIsSyncUps/TourOfSyncUps-0005-image.png
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/01-WhatIsSyncUps/TourOfSyncUps-0006-image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/01-WhatIsSyncUps/TourOfSyncUps-0006-image.png
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/01-WhatIsSyncUps/TourOfSyncUps-0007-image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/01-WhatIsSyncUps/TourOfSyncUps-0007-image.png
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/01-WhatIsSyncUps/TourOfSyncUps-0008-image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/01-WhatIsSyncUps/TourOfSyncUps-0008-image.png
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/01-WhatIsSyncUps/TourOfSyncUps-0009-image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/01-WhatIsSyncUps/TourOfSyncUps-0009-image.png
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/01-WhatIsSyncUps/TourOfSyncUps-0010-image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/01-WhatIsSyncUps/TourOfSyncUps-0010-image.png
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/01-WhatIsSyncUps/TourOfSyncUps-0011-image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/01-WhatIsSyncUps/TourOfSyncUps-0011-image.png
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/01-WhatIsSyncUps/TourOfSyncUps-0012-image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/01-WhatIsSyncUps/TourOfSyncUps-0012-image.png
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/01-WhatIsSyncUps/TourOfSyncUps-0013-image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/01-WhatIsSyncUps/TourOfSyncUps-0013-image.png
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/01-WhatIsSyncUps/TourOfSyncUps-0014-image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/01-WhatIsSyncUps/TourOfSyncUps-0014-image.png
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/02-ListsOfSyncUps/ListsOfSyncUps-01-code-0001.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/02-ListsOfSyncUps/ListsOfSyncUps-02-code-0001.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/02-ListsOfSyncUps/ListsOfSyncUps-02-code-0002.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 |
4 | @Reducer
5 | struct SyncUpsList {
6 |
7 | }
8 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/02-ListsOfSyncUps/ListsOfSyncUps-02-code-0003.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 |
4 | @Reducer
5 | struct SyncUpsList {
6 | @ObservableState
7 | struct State: Equatable {
8 | var syncUps: IdentifiedArrayOf = []
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/02-ListsOfSyncUps/ListsOfSyncUps-02-code-0004.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 |
4 | @Reducer
5 | struct SyncUpsList {
6 | @ObservableState
7 | struct State: Equatable {
8 | var syncUps: IdentifiedArrayOf = []
9 | }
10 | enum Action {
11 | case addSyncUpButtonTapped
12 | case onDelete(IndexSet)
13 | case syncUpTapped(id: SyncUp.ID)
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/02-ListsOfSyncUps/ListsOfSyncUps-02-code-0006-previous.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 |
4 | @Reducer
5 | struct SyncUpsList {
6 | // ...
7 | }
8 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/02-ListsOfSyncUps/ListsOfSyncUps-02-code-0010.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/02-ListsOfSyncUps/ListsOfSyncUps-02-code-0010.mp4
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/02-ListsOfSyncUps/ListsOfSyncUps-cover.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/02-ListsOfSyncUps/ListsOfSyncUps-cover.png
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/02-ListsOfSyncUps/TestingListOfSyncUps-01-code-0001.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import SyncUps
5 |
6 | @MainActor
7 | struct SyncUpsListTests {
8 | @Test
9 | func deletion() async {
10 |
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/02-ListsOfSyncUps/TestingListOfSyncUps-01-code-0002.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import SyncUps
5 |
6 | @MainActor
7 | struct SyncUpsListTests {
8 | @Test
9 | func deletion() async {
10 | let store = TestStore(
11 | initialState: SyncUpsList.State(
12 | syncUps: [
13 | SyncUp(
14 | id: SyncUp.ID(),
15 | title: "Point-Free Morning Sync"
16 | )
17 | ]
18 | )
19 | ) {
20 | SyncUpsList()
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/02-ListsOfSyncUps/TestingListOfSyncUps-01-code-0003.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import SyncUps
5 |
6 | @MainActor
7 | struct SyncUpsListTests {
8 | @Test
9 | func deletion() async {
10 | let store = TestStore(
11 | initialState: SyncUpsList.State(
12 | syncUps: [
13 | SyncUp(
14 | id: SyncUp.ID(),
15 | title: "Point-Free Morning Sync"
16 | )
17 | ]
18 | )
19 | ) {
20 | SyncUpsList()
21 | }
22 |
23 | await store.send(.onDelete([0]))
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/02-ListsOfSyncUps/TestingListOfSyncUps-01-code-0004.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import SyncUps
5 |
6 | @MainActor
7 | struct SyncUpsListTests {
8 | @Test
9 | func deletion() async {
10 | let store = TestStore(
11 | initialState: SyncUpsList.State(
12 | syncUps: [
13 | SyncUp(
14 | id: SyncUp.ID(),
15 | title: "Point-Free Morning Sync"
16 | )
17 | ]
18 | )
19 | ) {
20 | SyncUpsList()
21 | }
22 |
23 | await store.send(.onDelete([0])) {
24 | $0.syncUps = []
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/03-SyncUpForm/SyncUpForm-01-code-0001.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 |
4 | @Reducer
5 | struct SyncUpForm {
6 | @ObservableState
7 | struct State: Equatable {
8 | }
9 |
10 | enum Action {
11 | }
12 |
13 | var body: some ReducerOf {
14 | Reduce { state, action in
15 | switch action {
16 | }
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/03-SyncUpForm/SyncUpForm-01-code-0002.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 |
4 | @Reducer
5 | struct SyncUpForm {
6 | @ObservableState
7 | struct State: Equatable {
8 | var syncUp: SyncUp
9 | }
10 |
11 | enum Action {
12 | }
13 |
14 | var body: some ReducerOf {
15 | Reduce { state, action in
16 | switch action {
17 | }
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/03-SyncUpForm/SyncUpForm-01-code-0003.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 |
4 | @Reducer
5 | struct SyncUpForm {
6 | @ObservableState
7 | struct State: Equatable {
8 | var syncUp: SyncUp
9 | }
10 |
11 | enum Action: BindableAction {
12 | case binding(BindingAction)
13 | }
14 |
15 | var body: some ReducerOf {
16 | Reduce { state, action in
17 | switch action {
18 | }
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/03-SyncUpForm/SyncUpForm-01-code-0004.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 |
4 | @Reducer
5 | struct SyncUpForm {
6 | @ObservableState
7 | struct State: Equatable {
8 | var syncUp: SyncUp
9 | }
10 |
11 | enum Action: BindableAction {
12 | case binding(BindingAction)
13 | }
14 |
15 | var body: some ReducerOf {
16 | BindingReducer()
17 |
18 | Reduce { state, action in
19 | switch action {
20 | case .binding:
21 | return .none
22 | }
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/03-SyncUpForm/SyncUpForm-01-code-0007.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 |
4 | @Reducer
5 | struct SyncUpForm {
6 | // ...
7 | }
8 |
9 | struct SyncUpFormView: View {
10 | var body: some View {
11 | Form {
12 |
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/03-SyncUpForm/SyncUpForm-01-code-0008.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 |
4 | @Reducer
5 | struct SyncUpForm {
6 | // ...
7 | }
8 |
9 | struct SyncUpFormView: View {
10 | @Bindable var store: StoreOf
11 |
12 | var body: some View {
13 | Form {
14 |
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/03-SyncUpForm/SyncUpForm-02-video-0007.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/03-SyncUpForm/SyncUpForm-02-video-0007.mp4
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/03-SyncUpForm/SyncUpFormBasics-01-0000.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/03-SyncUpForm/SyncUpFormBasics-01-0000.png
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/03-SyncUpForm/TestingSyncUpForm-01-code-0001.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import SyncUps
5 |
6 | @MainActor
7 | struct SyncUpFormTests {
8 | @Test
9 | func removeAttendee() async {
10 |
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/03-SyncUpForm/TestingSyncUpForm-01-code-0002.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import SyncUps
5 |
6 | @MainActor
7 | struct SyncUpFormTests {
8 | @Test
9 | func removeAttendee() async {
10 | let store = TestStore(
11 | initialState: SyncUpForm.State(
12 | syncUp: SyncUp(
13 | id: SyncUp.ID(),
14 | attendees: [
15 | Attendee(id: Attendee.ID()),
16 | Attendee(id: Attendee.ID())
17 | ]
18 | )
19 | )
20 | ) {
21 | SyncUpForm()
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/03-SyncUpForm/TestingSyncUpForm-01-code-0003.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import SyncUps
5 |
6 | @MainActor
7 | struct SyncUpFormTests {
8 | @Test
9 | func removeAttendee() async {
10 | let store = TestStore(
11 | initialState: SyncUpForm.State(
12 | syncUp: SyncUp(
13 | id: SyncUp.ID(),
14 | attendees: [
15 | Attendee(id: Attendee.ID()),
16 | Attendee(id: Attendee.ID())
17 | ]
18 | )
19 | )
20 | ) {
21 | SyncUpForm()
22 | }
23 |
24 | await store.send(.onDeleteAttendees([0])) {
25 | $0.syncUp.attendees.removeFirst()
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/03-SyncUpForm/TestingSyncUpForm-01-code-0004-previous.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import SyncUps
5 |
6 | @MainActor
7 | struct SyncUpFormTests {
8 | @Test
9 | func removeAttendee() async {
10 | // ...
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/03-SyncUpForm/TestingSyncUpForm-01-code-0004.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import SyncUps
5 |
6 | @MainActor
7 | struct SyncUpFormTests {
8 | @Test
9 | func removeFocusedAttendee() async {
10 | let attendee1 = Attendee(id: Attendee.ID())
11 | let attendee2 = Attendee(id: Attendee.ID())
12 | let store = TestStore(
13 | initialState: SyncUpForm.State(
14 | focus: .attendee(attendee1.id),
15 | syncUp: SyncUp(
16 | id: SyncUp.ID(),
17 | attendees: [attendee1, attendee2]
18 | )
19 | )
20 | ) {
21 | SyncUpForm()
22 | }
23 | }
24 |
25 | @Test
26 | func removeAttendee() async {
27 | // ...
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/03-SyncUpForm/TestingSyncUpForm-02-code-0001-previous.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import SyncUps
5 |
6 | @MainActor
7 | struct SyncUpFormTests {
8 | @Test
9 | func removeFocusedAttendee() async {
10 | // ...
11 | }
12 |
13 | @Test
14 | func removeAttendee() async {
15 | // ...
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/03-SyncUpForm/TestingSyncUpForm-02-code-0001.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import SyncUps
5 |
6 | @MainActor
7 | struct SyncUpFormTests {
8 | @Test
9 | func addAttendee() async {
10 | let store = TestStore(
11 | initialState: SyncUpForm.State(
12 | syncUp: SyncUp(id: SyncUp.ID())
13 | )
14 | ) {
15 | SyncUpForm()
16 | }
17 | }
18 |
19 | @Test
20 | func removeFocusedAttendee() async {
21 | // ...
22 | }
23 |
24 | @Test
25 | func removeAttendee() async {
26 | // ...
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/04-PresentingSyncUpForm/PresentingSyncUpForm-02-video-0004.mov:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/04-PresentingSyncUpForm/PresentingSyncUpForm-02-video-0004.mov
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/04-PresentingSyncUpForm/PresentingSyncUpForm-03-code-0006.mov:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/04-PresentingSyncUpForm/PresentingSyncUpForm-03-code-0006.mov
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/04-PresentingSyncUpForm/TestingSyncUpFormPresentation-01-code-0001-previous.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import SyncUps
5 |
6 | @MainActor
7 | struct SyncUpsListTests {
8 | @Test
9 | func deletion() async {
10 | // ...
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/04-PresentingSyncUpForm/TestingSyncUpFormPresentation-01-code-0001.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import SyncUps
5 |
6 | @MainActor
7 | struct SyncUpsListTests {
8 | @Test
9 | func addSyncUp() async {
10 |
11 | }
12 |
13 | @Test
14 | func deletion() async {
15 | // ...
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/04-PresentingSyncUpForm/TestingSyncUpFormPresentation-01-code-0002.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import SyncUps
5 |
6 | @MainActor
7 | struct SyncUpsListTests {
8 | @Test
9 | func addSyncUp() async {
10 | let store = TestStore(initialState: SyncUpsList.State()) {
11 | SyncUpsList()
12 | }
13 | }
14 |
15 | @Test
16 | func deletion() async {
17 | // ...
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/04-PresentingSyncUpForm/TestingSyncUpFormPresentation-01-code-0003.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import SyncUps
5 |
6 | @MainActor
7 | struct SyncUpsListTests {
8 | @Test
9 | func addSyncUp() async {
10 | let store = TestStore(initialState: SyncUpsList.State()) {
11 | SyncUpsList()
12 | }
13 |
14 | await store.send(.addSyncUpButtonTapped) {
15 | $0.addSyncUp = SyncUpForm.State(syncUp: SyncUp(id: SyncUp.ID()))
16 | }
17 | }
18 |
19 | @Test
20 | func deletion() async {
21 | // ...
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/04-PresentingSyncUpForm/TestingSyncUpFormPresentation-01-code-0007-previous.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import SyncUps
5 |
6 | @MainActor
7 | struct SyncUpsListTests {
8 | @Test
9 | func addSyncUp() async {
10 | let store = TestStore(initialState: SyncUpsList.State()) {
11 | SyncUpsList()
12 | }
13 |
14 | await store.send(.addSyncUpButtonTapped) {
15 | $0.addSyncUp = SyncUpForm.State(syncUp: SyncUp(id: SyncUp.ID()))
16 | }
17 | }
18 |
19 | @Test
20 | func deletion() async {
21 | // ...
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/04-PresentingSyncUpForm/TestingSyncUpFormPresentation-01-code-0007.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import SyncUps
5 |
6 | @MainActor
7 | struct SyncUpsListTests {
8 | @Test
9 | func addSyncUp() async {
10 | let store = TestStore(initialState: SyncUpsList.State()) {
11 | SyncUpsList()
12 | } withDependencies: {
13 | $0.uuid = .incrementing
14 | }
15 |
16 | await store.send(.addSyncUpButtonTapped) {
17 | $0.addSyncUp = SyncUpForm.State(syncUp: SyncUp(id: SyncUp.ID()))
18 | }
19 | }
20 |
21 | @Test
22 | func deletion() async {
23 | // ...
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/04-PresentingSyncUpForm/TestingSyncUpFormPresentation-01-code-0008.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import SyncUps
5 |
6 | @MainActor
7 | struct SyncUpsListTests {
8 | @Test
9 | func addSyncUp() async {
10 | let store = TestStore(initialState: SyncUpsList.State()) {
11 | SyncUpsList()
12 | } withDependencies: {
13 | $0.uuid = .incrementing
14 | }
15 |
16 | await store.send(.addSyncUpButtonTapped) {
17 | $0.addSyncUp = SyncUpForm.State(
18 | syncUp: SyncUp(id: SyncUp.ID(0))
19 | )
20 | }
21 | }
22 |
23 | @Test
24 | func deletion() async {
25 | // ...
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/04-PresentingSyncUpForm/TestingSyncUpFormPresentation-01-code-0009.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import SyncUps
5 |
6 | @MainActor
7 | struct SyncUpsListTests {
8 | @Test
9 | func addSyncUp() async {
10 | let store = TestStore(initialState: SyncUpsList.State()) {
11 | SyncUpsList()
12 | } withDependencies: {
13 | $0.uuid = .incrementing
14 | }
15 |
16 | await store.send(.addSyncUpButtonTapped) {
17 | $0.addSyncUp = SyncUpForm.State(
18 | syncUp: SyncUp(id: SyncUp.ID(0))
19 | )
20 | }
21 |
22 | await store.send(\.addSyncUp…)
23 | }
24 |
25 | @Test
26 | func deletion() async {
27 | // ...
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/04-PresentingSyncUpForm/TestingSyncUpFormPresentation-01-code-0010.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import SyncUps
5 |
6 | @MainActor
7 | struct SyncUpsListTests {
8 | @Test
9 | func addSyncUp() async {
10 | let store = TestStore(initialState: SyncUpsList.State()) {
11 | SyncUpsList()
12 | } withDependencies: {
13 | $0.uuid = .incrementing
14 | }
15 |
16 | await store.send(.addSyncUpButtonTapped) {
17 | $0.addSyncUp = SyncUpForm.State(
18 | syncUp: SyncUp(id: SyncUp.ID(0))
19 | )
20 | }
21 |
22 | await store.send(\.addSyncUp.binding…)
23 | }
24 |
25 | @Test
26 | func deletion() async {
27 | // ...
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/04-PresentingSyncUpForm/TestingSyncUpFormPresentation-02-code-0001-previous.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import SyncUps
5 |
6 | @MainActor
7 | struct SyncUpsListTests {
8 | @Test
9 | func addSyncUp() async {
10 | // ...
11 | }
12 |
13 | @Test
14 | func deletion() async {
15 | // ...
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/04-PresentingSyncUpForm/TestingSyncUpFormPresentation-02-code-0001.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import SyncUps
5 |
6 | @MainActor
7 | struct SyncUpsListTests {
8 | @Test
9 | func addSyncUpNonExhaustive() async {
10 |
11 | }
12 |
13 | @Test
14 | func addSyncUp() async {
15 | // ...
16 | }
17 |
18 | @Test
19 | func deletion() async {
20 | // ...
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/04-PresentingSyncUpForm/TestingSyncUpFormPresentation-02-code-0002.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import SyncUps
5 |
6 | @MainActor
7 | struct SyncUpsListTests {
8 | @Test
9 | func addSyncUpNonExhaustive() async {
10 | let store = TestStore(initialState: SyncUpsList.State()) {
11 | SyncUpsList()
12 | } withDependencies: {
13 | $0.uuid = .incrementing
14 | }
15 | store.exhaustivity = .off
16 | }
17 |
18 | @Test
19 | func addSyncUp() async {
20 | // ...
21 | }
22 |
23 | @Test
24 | func deletion() async {
25 | // ...
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/04-PresentingSyncUpForm/TestingSyncUpFormPresentation-02-code-0003.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import SyncUps
5 |
6 | @MainActor
7 | struct SyncUpsListTests {
8 | @Test
9 | func addSyncUpNonExhaustive() async {
10 | let store = TestStore(initialState: SyncUpsList.State()) {
11 | SyncUpsList()
12 | } withDependencies: {
13 | $0.uuid = .incrementing
14 | }
15 | store.exhaustivity = .off
16 |
17 | await store.send(.addSyncUpButtonTapped)
18 | }
19 |
20 | @Test
21 | func addSyncUp() async {
22 | // ...
23 | }
24 |
25 | @Test
26 | func deletion() async {
27 | // ...
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/05-PersistingSyncUps/PersistingSyncUps-01-code-0006-previous.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 |
4 | @Reducer
5 | struct SyncUpsList {
6 | // ...
7 | }
8 |
9 | struct SyncUpsListView: View {
10 | // ...
11 | }
12 |
13 | #Preview {
14 | NavigationStack {
15 | SyncUpsListView(
16 | store: Store(
17 | initialState: SyncUpsList.State(
18 | syncUps: [.mock]
19 | )
20 | ) {
21 | SyncUpsList()
22 | ._printChanges()
23 | }
24 | )
25 | }
26 | }
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/05-PersistingSyncUps/PersistingSyncUps-01-code-0006.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 |
4 | @Reducer
5 | struct SyncUpsList {
6 | // ...
7 | }
8 |
9 | struct SyncUpsListView: View {
10 | // ...
11 | }
12 |
13 | #Preview {
14 | @Shared(.syncUps) var syncUps = [.mock]
15 | NavigationStack {
16 | SyncUpsListView(
17 | store: Store(
18 | initialState: SyncUpsList.State()
19 | ) {
20 | SyncUpsList()
21 | ._printChanges()
22 | }
23 | )
24 | }
25 | }
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/05-PersistingSyncUps/PersistingSyncUps-01-code-0007.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 |
4 | @main
5 | struct SyncUpsApp: App {
6 | @MainActor
7 | static let store = Store(initialState: SyncUpsList.State()) {
8 | SyncUpsList()
9 | }
10 |
11 | var body: some Scene {
12 | WindowGroup {
13 | NavigationStack {
14 | SyncUpsListView(store: Self.store)
15 | }
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/05-PersistingSyncUps/PersistingSyncUps-01-video-0008.mov:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/05-PersistingSyncUps/PersistingSyncUps-01-video-0008.mov
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/06-SyncUpDetail/EditingAndDeletingSyncUp-01-code-0001-previous.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 |
4 | @Reducer
5 | struct SyncUpDetail {
6 | @ObservableState
7 | struct State: Equatable {
8 | @Shared var syncUp: SyncUp
9 | }
10 |
11 | enum Action {
12 | case deleteButtonTapped
13 | case editButtonTapped
14 | }
15 |
16 | var body: some ReducerOf {
17 | Reduce { state, action in
18 | switch action {
19 | case .deleteButtonTapped:
20 | return .none
21 |
22 | case .editButtonTapped:
23 | return .none
24 | }
25 | }
26 | }
27 | }
28 |
29 | struct SyncUpDetailView: View {
30 | // ...
31 | }
32 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/06-SyncUpDetail/EditingAndDeletingSyncUp-01-code-0001.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 |
4 | @Reducer
5 | struct SyncUpDetail {
6 | @ObservableState
7 | struct State: Equatable {
8 | @Presents var editSyncUp: SyncUpForm.State?
9 | @Shared var syncUp: SyncUp
10 | }
11 |
12 | enum Action {
13 | case deleteButtonTapped
14 | case editButtonTapped
15 | }
16 |
17 | var body: some ReducerOf {
18 | Reduce { state, action in
19 | switch action {
20 | case .deleteButtonTapped:
21 | return .none
22 |
23 | case .editButtonTapped:
24 | return .none
25 | }
26 | }
27 | }
28 | }
29 |
30 | struct SyncUpDetailView: View {
31 | // ...
32 | }
33 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/06-SyncUpDetail/EditingAndDeletingSyncUp-01-cover-480p.mov:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/06-SyncUpDetail/EditingAndDeletingSyncUp-01-cover-480p.mov
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/06-SyncUpDetail/EditingAndDeletingSyncUp-02-cover-480p.mov:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/06-SyncUpDetail/EditingAndDeletingSyncUp-02-cover-480p.mov
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/06-SyncUpDetail/EditingAndDeletingSyncUp-03-code-0001-previous.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 |
4 | @Reducer
5 | struct SyncUpDetail {
6 | // ...
7 | }
8 |
9 | struct SyncUpDetailView: View {
10 | // ...
11 | }
12 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/06-SyncUpDetail/EditingAndDeletingSyncUp-03-code-0001.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 |
4 | @Reducer
5 | struct SyncUpDetail {
6 | @Reducer
7 | enum Destination {
8 | }
9 | // ...
10 | }
11 | extension SyncUpDetail.Destination.State: Equatable {}
12 |
13 | struct SyncUpDetailView: View {
14 | // ...
15 | }
16 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/06-SyncUpDetail/EditingAndDeletingSyncUp-03-code-0002.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 |
4 | @Reducer
5 | struct SyncUpDetail {
6 | @Reducer
7 | enum Destination {
8 | case alert(AlertState)
9 | case edit(SyncUpForm)
10 | @CasePathable
11 | enum Alert {
12 | case confirmButtonTapped
13 | }
14 | }
15 | // ...
16 | }
17 | extension SyncUpDetail.Destination.State: Equatable {}
18 |
19 | struct SyncUpDetailView: View {
20 | // ...
21 | }
22 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/06-SyncUpDetail/SyncUpDetail-01-code-0001.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 |
4 | @Reducer
5 | struct SyncUpDetail {
6 | @ObservableState
7 | struct State: Equatable {
8 | }
9 |
10 | enum Action {
11 | }
12 |
13 | var body: some ReducerOf {
14 | Reduce { state, action in
15 | switch action {
16 | }
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/06-SyncUpDetail/SyncUpDetail-01-code-0002.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 |
4 | @Reducer
5 | struct SyncUpDetail {
6 | @ObservableState
7 | struct State: Equatable {
8 | @Shared var syncUp: SyncUp
9 | }
10 |
11 | enum Action {
12 | }
13 |
14 | var body: some ReducerOf {
15 | Reduce { state, action in
16 | switch action {
17 | }
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/06-SyncUpDetail/SyncUpDetail-01-code-0003.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 |
4 | @Reducer
5 | struct SyncUpDetail {
6 | @ObservableState
7 | struct State: Equatable {
8 | @Shared var syncUp: SyncUp
9 | }
10 |
11 | enum Action {
12 | case deleteButtonTapped
13 | case editButtonTapped
14 | }
15 |
16 | var body: some ReducerOf {
17 | Reduce { state, action in
18 | switch action {
19 | }
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/06-SyncUpDetail/SyncUpDetail-01-code-0004.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 |
4 | @Reducer
5 | struct SyncUpDetail {
6 | @ObservableState
7 | struct State: Equatable {
8 | @Shared var syncUp: SyncUp
9 | }
10 |
11 | enum Action {
12 | case deleteButtonTapped
13 | case editButtonTapped
14 | }
15 |
16 | var body: some ReducerOf {
17 | Reduce { state, action in
18 | switch action {
19 | case .deleteButtonTapped:
20 | return .none
21 |
22 | case .editButtonTapped:
23 | return .none
24 | }
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/06-SyncUpDetail/SyncUpDetail-01-code-0005.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 |
4 | @Reducer
5 | struct SyncUpDetail {
6 | // ...
7 | }
8 |
9 | struct SyncUpDetailView: View {
10 | let store: StoreOf
11 |
12 | var body: some View {
13 | Form {
14 |
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/06-SyncUpDetail/SyncUpDetail-01-image-0007.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/06-SyncUpDetail/SyncUpDetail-01-image-0007.png
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/06-SyncUpDetail/SyncUpDetail-cover.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/06-SyncUpDetail/SyncUpDetail-cover.png
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/06-SyncUpDetail/TestingSyncUpDetail-01-code-0001.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import SyncUps
5 |
6 | @MainActor
7 | struct SyncUpDetailTests {
8 | @Test
9 | func edit() async {
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/06-SyncUpDetail/TestingSyncUpDetail-01-code-0002.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import SyncUps
5 |
6 | @MainActor
7 | struct SyncUpDetailTests {
8 | @Test
9 | func edit() async {
10 | let syncUp = SyncUp(
11 | id: SyncUp.ID(),
12 | title: "Point-Free Morning Sync"
13 | )
14 | let store = TestStore(initialState: SyncUpDetail.State(syncUp: Shared(value: syncUp))) {
15 | SyncUpDetail()
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/06-SyncUpDetail/TestingSyncUpDetail-01-code-0003.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import SyncUps
5 |
6 | @MainActor
7 | struct SyncUpDetailTests {
8 | @Test
9 | func edit() async {
10 | let syncUp = SyncUp(
11 | id: SyncUp.ID(),
12 | title: "Point-Free Morning Sync"
13 | )
14 | let store = TestStore(initialState: SyncUpDetail.State(syncUp: Shared(value: syncUp))) {
15 | SyncUpDetail()
16 | }
17 |
18 | await store.send(.editButtonTapped) {
19 | $0.destination = .edit(SyncUpForm.State(syncUp: syncUp))
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/07-SyncUpDetailNavigation/MeetingNavigation-01-code-0001.swift:
--------------------------------------------------------------------------------
1 | import SwiftUI
2 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/07-SyncUpDetailNavigation/MeetingNavigation-01-code-0002.swift:
--------------------------------------------------------------------------------
1 | import SwiftUI
2 |
3 | struct MeetingView: View {
4 | let meeting: Meeting
5 | let syncUp: SyncUp
6 | }
7 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/07-SyncUpDetailNavigation/MeetingNavigation-01-code-0003.swift:
--------------------------------------------------------------------------------
1 | import SwiftUI
2 |
3 | struct MeetingView: View {
4 | let meeting: Meeting
5 | let syncUp: SyncUp
6 |
7 | var body: some View {
8 | Form {
9 | Section {
10 | ForEach(syncUp.attendees) { attendee in
11 | Text(attendee.name)
12 | }
13 | } header: {
14 | Text("Attendees")
15 | }
16 | Section {
17 | Text(meeting.transcript)
18 | } header: {
19 | Text("Transcript")
20 | }
21 | }
22 | .navigationTitle(Text(meeting.date, style: .date))
23 | }
24 | }
25 |
26 | #Preview {
27 | MeetingView(meeting: SyncUp.mock.meetings[0], syncUp: .mock)
28 | }
29 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/07-SyncUpDetailNavigation/MeetingNavigation-01-cover.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/07-SyncUpDetailNavigation/MeetingNavigation-01-cover.png
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/07-SyncUpDetailNavigation/MeetingNavigation-02-code-0001.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 |
4 | @Reducer
5 | struct App {
6 | @Reducer
7 | enum Path {
8 | case detail(SyncUpDetail)
9 | }
10 | // ...
11 | }
12 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/07-SyncUpDetailNavigation/MeetingNavigation-02-code-0002.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 |
4 | @Reducer
5 | struct App {
6 | @Reducer
7 | enum Path {
8 | case detail(SyncUpDetail)
9 | case meeting(Meeting, syncUp: SyncUp)
10 | }
11 | // ...
12 | }
13 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/07-SyncUpDetailNavigation/SyncUpDetailNavigation-01-code-0001.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 |
4 | @Reducer
5 | struct AppFeature {
6 | @ObservableState
7 | struct State: Equatable {
8 | }
9 | enum Action {
10 | }
11 | var body: some ReducerOf {
12 | Reduce { state, action in
13 | switch action {
14 | }
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/07-SyncUpDetailNavigation/SyncUpDetailNavigation-01-code-0002.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 |
4 | @Reducer
5 | struct AppFeature {
6 | @ObservableState
7 | struct State: Equatable {
8 | var syncUpsList = SyncUpsList.State()
9 | }
10 | enum Action {
11 | case syncUpsList(SyncUpsList.Action)
12 | }
13 | var body: some ReducerOf {
14 | Scope(state: \.syncUpsList, action: \.syncUpsList) {
15 | SyncUpsList()
16 | }
17 | Reduce { state, action in
18 | switch action {
19 | case .syncUpsList:
20 | return .none
21 | }
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/07-SyncUpDetailNavigation/SyncUpDetailNavigation-01-code-0003.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 |
4 | @Reducer
5 | struct AppFeature {
6 | @ObservableState
7 | struct State: Equatable {
8 | var path = StackState()
9 | var syncUpsList = SyncUpsList.State()
10 | }
11 | enum Action {
12 | case syncUpsList(SyncUpsList.Action)
13 | }
14 | var body: some ReducerOf {
15 | Scope(state: \.syncUpsList, action: \.syncUpsList) {
16 | SyncUpsList()
17 | }
18 | Reduce { state, action in
19 | switch action {
20 | case .syncUpsList:
21 | return .none
22 | }
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/07-SyncUpDetailNavigation/SyncUpDetailNavigation-01-code-0004.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 |
4 | @Reducer
5 | struct AppFeature {
6 | @Reducer
7 | enum Path {
8 | }
9 | @ObservableState
10 | struct State: Equatable {
11 | var path = StackState()
12 | var syncUpsList = SyncUpsList.State()
13 | }
14 | enum Action {
15 | case syncUpsList(SyncUpsList.Action)
16 | }
17 | var body: some ReducerOf {
18 | Scope(state: \.syncUpsList, action: \.syncUpsList) {
19 | SyncUpsList()
20 | }
21 | Reduce { state, action in
22 | switch action {
23 | case .syncUpsList:
24 | return .none
25 | }
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/07-SyncUpDetailNavigation/SyncUpDetailNavigation-02-code-0001-previous.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 |
4 | @Reducer
5 | struct AppFeature {
6 | // ...
7 | }
8 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/07-SyncUpDetailNavigation/SyncUpDetailNavigation-02-code-0001.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 |
4 | @Reducer
5 | struct AppFeature {
6 | // ...
7 | }
8 |
9 | struct AppView: View {
10 | }
11 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/07-SyncUpDetailNavigation/SyncUpDetailNavigation-02-code-0002.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 |
4 | @Reducer
5 | struct AppFeature {
6 | // ...
7 | }
8 |
9 | struct AppView: View {
10 | @Bindable var store: StoreOf
11 | }
12 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/07-SyncUpDetailNavigation/SyncUpDetailNavigation-02-code-0003.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 |
4 | @Reducer
5 | struct AppFeature {
6 | // ...
7 | }
8 |
9 | struct AppView: View {
10 | @Bindable var store: StoreOf
11 |
12 | var body: some View {
13 | NavigationStack(
14 | path: $store.scope(state: \.path, action: \.path)
15 | ) {
16 |
17 | } destination: { store in
18 |
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/07-SyncUpDetailNavigation/SyncUpDetailNavigation-02-code-0004.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 |
4 | @Reducer
5 | struct AppFeature {
6 | // ...
7 | }
8 |
9 | struct AppView: View {
10 | @Bindable var store: StoreOf
11 |
12 | var body: some View {
13 | NavigationStack(
14 | path: $store.scope(state: \.path, action: \.path)
15 | ) {
16 | SyncUpsListView(
17 | store: store.scope(state: \.syncUpsList, action: \.syncUpsList)
18 | )
19 | } destination: { store in
20 |
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/07-SyncUpDetailNavigation/SyncUpDetailNavigation-02-code-0005.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 |
4 | @Reducer
5 | struct AppFeature {
6 | // ...
7 | }
8 |
9 | struct AppView: View {
10 | @Bindable var store: StoreOf
11 |
12 | var body: some View {
13 | NavigationStack(
14 | path: $store.scope(state: \.path, action: \.path)
15 | ) {
16 | SyncUpsListView(
17 | store: store.scope(state: \.syncUpsList, action: \.syncUpsList)
18 | )
19 | } destination: { store in
20 | switch store.case {
21 | case let .detail(detailStore):
22 |
23 | }
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/07-SyncUpDetailNavigation/SyncUpDetailNavigation-02-code-0006.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 |
4 | @Reducer
5 | struct AppFeature {
6 | // ...
7 | }
8 |
9 | struct AppView: View {
10 | @Bindable var store: StoreOf
11 |
12 | var body: some View {
13 | NavigationStack(
14 | path: $store.scope(state: \.path, action: \.path)
15 | ) {
16 | SyncUpsListView(
17 | store: store.scope(state: \.syncUpsList, action: \.syncUpsList)
18 | )
19 | } destination: { store in
20 | switch store.case {
21 | case let .detail(detailStore):
22 | SyncUpDetailView(store: detailStore)
23 | }
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/07-SyncUpDetailNavigation/SyncUpDetailNavigation-03-video-0005.mov:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/07-SyncUpDetailNavigation/SyncUpDetailNavigation-03-video-0005.mov
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/07-SyncUpDetailNavigation/SyncUpDetailNavigation-03-video-0006.mov:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/07-SyncUpDetailNavigation/SyncUpDetailNavigation-03-video-0006.mov
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/07-SyncUpDetailNavigation/TestingNavigation-01-code-0001.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import SyncUps
5 |
6 | @MainActor
7 | struct AppFeatureTests {
8 | @Test
9 | func delete() async throws {
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/07-SyncUpDetailNavigation/TestingNavigation-01-code-0002.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import SyncUps
5 |
6 | @MainActor
7 | struct AppFeatureTests {
8 | @Test
9 | func delete() async throws {
10 | let syncUp = SyncUp.mock
11 | @Shared(.syncUps) var syncUps = [syncUp]
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/07-SyncUpDetailNavigation/TestingNavigation-01-code-0003.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import SyncUps
5 |
6 | @MainActor
7 | struct AppFeatureTests {
8 | @Test
9 | func delete() async throws {
10 | let syncUp = SyncUp.mock
11 | @Shared(.syncUps) var syncUps = [syncUp]
12 |
13 | let store = TestStore(initialState: AppFeature.State()) {
14 | AppFeature()
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/07-SyncUpDetailNavigation/TestingNavigation-01-code-0004.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import SyncUps
5 |
6 | @MainActor
7 | struct AppFeatureTests {
8 | @Test
9 | func delete() async throws {
10 | let syncUp = SyncUp.mock
11 | @Shared(.syncUps) var syncUps = [syncUp]
12 |
13 | let store = TestStore(initialState: AppFeature.State()) {
14 | AppFeature()
15 | }
16 |
17 | await store.send(\.path.push, (id: 0, .detail(SyncUpDetail.State(syncUp: ???)))) {
18 |
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/07-SyncUpDetailNavigation/TestingNavigation-01-code-0005.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import SyncUps
5 |
6 | @MainActor
7 | struct AppFeatureTests {
8 | @Test
9 | func delete() async throws {
10 | let syncUp = SyncUp.mock
11 | @Shared(.syncUps) var syncUps = [syncUp]
12 |
13 | let store = TestStore(initialState: AppFeature.State()) {
14 | AppFeature()
15 | }
16 |
17 | let sharedSyncUp = try #require(Shared($syncUps[id: syncUp.id]))
18 |
19 | await store.send(\.path.push, (id: 0, .detail(SyncUpDetail.State(syncUp: sharedSyncUp)))) {
20 | $0.path[id: 0] = .detail(SyncUpDetail.State(syncUp: sharedSyncUp))
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/08-RecordMeeting/ImplementingTimer-01-code-0011-previous.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 |
4 | @Reducer
5 | struct App {
6 | // ...
7 | }
8 |
9 | struct AppView: View {
10 | // ...
11 | }
12 |
13 | #Preview {
14 | AppView(
15 | store: Store(
16 | initialState: App.State(
17 | syncUpsList: SyncUpsList.State()
18 | )
19 | ) {
20 | App()
21 | }
22 | )
23 | }
24 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/08-RecordMeeting/ImplementingTimer-01-video-0012.mov:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/08-RecordMeeting/ImplementingTimer-01-video-0012.mov
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/08-RecordMeeting/ImplementingTimer-03-video-0009.mov:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/08-RecordMeeting/ImplementingTimer-03-video-0009.mov
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/08-RecordMeeting/ImplementingTimer-04-code-0001.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import SyncUps
5 |
6 | @MainActor
7 | struct RecordMeetingTests {
8 | @Test
9 | func timerFinishes() async {
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/08-RecordMeeting/ImplementingTimer-04-code-0002.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import SyncUps
5 |
6 | @MainActor
7 | struct RecordMeetingTests {
8 | @Test
9 | func timerFinishes() async {
10 | let syncUp = SyncUp(
11 | id: SyncUp.ID(),
12 | attendees: [
13 | Attendee(id: Attendee.ID(), name: "Blob"),
14 | Attendee(id: Attendee.ID(), name: "Blob Jr"),
15 | ],
16 | duration: .seconds(4),
17 | title: "Morning Sync"
18 | )
19 | let store = TestStore(
20 | initialState: RecordMeeting.State(syncUp: Shared(value: syncUp))
21 | ) {
22 | RecordMeeting()
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/08-RecordMeeting/ImplementingTimer-04-code-0003.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import SyncUps
5 |
6 | @MainActor
7 | struct RecordMeetingTests {
8 | @Test
9 | func timerFinishes() async {
10 | let syncUp = SyncUp(
11 | id: SyncUp.ID(),
12 | attendees: [
13 | Attendee(id: Attendee.ID(), name: "Blob"),
14 | Attendee(id: Attendee.ID(), name: "Blob Jr"),
15 | ],
16 | duration: .seconds(4),
17 | title: "Morning Sync"
18 | )
19 | let store = TestStore(
20 | initialState: RecordMeeting.State(syncUp: Shared(value: syncUp))
21 | ) {
22 | RecordMeeting()
23 | }
24 |
25 | await store.send(.onAppear)
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/08-RecordMeeting/RecordMeetingFeature-01-code-0001.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 |
4 | @Reducer
5 | struct RecordMeeting {
6 | }
7 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/08-RecordMeeting/RecordMeetingFeature-01-code-0002.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 |
3 | @Reducer
4 | struct RecordMeeting {
5 | @ObservableState
6 | struct State: Equatable {
7 | var secondsElapsed = 0
8 | var speakerIndex = 0
9 | @Shared var syncUp: SyncUp
10 | var transcript = ""
11 |
12 | var durationRemaining: Duration {
13 | syncUp.duration - .seconds(secondsElapsed)
14 | }
15 | }
16 |
17 | enum Action {
18 | case endMeetingButtonTapped
19 | case nextButtonTapped
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/08-RecordMeeting/RecordMeetingFeature-01-image-0004.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/08-RecordMeeting/RecordMeetingFeature-01-image-0004.jpg
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/08-RecordMeeting/RecordMeetingFeature-02-code-0001-previous.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 |
4 | @Reducer
5 | struct App {
6 | // ...
7 | }
8 |
9 | extension App {
10 | @Reducer
11 | enum Path {
12 | case detail(SyncUpDetail)
13 | case meeting(Meeting, syncUp: SyncUp)
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/08-RecordMeeting/RecordMeetingFeature-02-code-0001.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 |
4 | @Reducer
5 | struct App {
6 | // ...
7 | }
8 |
9 | extension App {
10 | @Reducer
11 | enum Path {
12 | case detail(SyncUpDetail)
13 | case meeting(Meeting, syncUp: SyncUp)
14 | case record(RecordMeeting)
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/08-RecordMeeting/RecordMeetingFeature-02-video-0004.mov:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Sources/ComposableArchitecture/Documentation.docc/Tutorials/BuildingSyncUps/08-RecordMeeting/RecordMeetingFeature-02-video-0004.mov
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/01-Essentials/01-YourFirstFeature/01-01-01-code-0001.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/01-Essentials/01-YourFirstFeature/01-01-01-code-0002.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 |
3 | @Reducer
4 | struct CounterFeature {
5 |
6 | }
7 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/01-Essentials/01-YourFirstFeature/01-01-01-code-0003.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 |
3 | @Reducer
4 | struct CounterFeature {
5 | @ObservableState
6 | struct State {
7 |
8 | }
9 |
10 | enum Action {
11 |
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/01-Essentials/01-YourFirstFeature/01-01-01-code-0004.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 |
3 | @Reducer
4 | struct CounterFeature {
5 | @ObservableState
6 | struct State {
7 | var count = 0
8 | }
9 |
10 | enum Action {
11 | case decrementButtonTapped
12 | case incrementButtonTapped
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/01-Essentials/01-YourFirstFeature/01-01-01-code-0005.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 |
3 | @Reducer
4 | struct CounterFeature {
5 | @ObservableState
6 | struct State {
7 | var count = 0
8 | }
9 |
10 | enum Action {
11 | case decrementButtonTapped
12 | case incrementButtonTapped
13 | }
14 |
15 | var body: some ReducerOf {
16 | Reduce { state, action in
17 | switch action {
18 | case .decrementButtonTapped:
19 |
20 | case .incrementButtonTapped:
21 |
22 | }
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/01-Essentials/01-YourFirstFeature/01-01-01-code-0006.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 |
3 | @Reducer
4 | struct CounterFeature {
5 | @ObservableState
6 | struct State {
7 | var count = 0
8 | }
9 |
10 | enum Action {
11 | case decrementButtonTapped
12 | case incrementButtonTapped
13 | }
14 |
15 | var body: some ReducerOf {
16 | Reduce { state, action in
17 | switch action {
18 | case .decrementButtonTapped:
19 | state.count -= 1
20 | return .none
21 |
22 | case .incrementButtonTapped:
23 | state.count += 1
24 | return .none
25 | }
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/01-Essentials/01-YourFirstFeature/01-01-02-code-0001.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 |
4 | struct CounterView: View {
5 | var body: some View {
6 | EmptyView()
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/01-Essentials/01-YourFirstFeature/01-01-02-code-0002.swift:
--------------------------------------------------------------------------------
1 | struct CounterView: View {
2 | let store: StoreOf
3 |
4 | var body: some View {
5 | EmptyView()
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/01-Essentials/01-YourFirstFeature/01-01-02-code-0005.swift:
--------------------------------------------------------------------------------
1 | #Preview {
2 | CounterView(
3 | store: Store(initialState: CounterFeature.State()) {
4 | CounterFeature()
5 | }
6 | )
7 | }
8 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/01-Essentials/01-YourFirstFeature/01-01-02-code-0006.swift:
--------------------------------------------------------------------------------
1 | #Preview {
2 | CounterView(
3 | store: Store(initialState: CounterFeature.State()) {
4 | // CounterFeature()
5 | }
6 | )
7 | }
8 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/01-Essentials/01-YourFirstFeature/01-01-02-code-0007.swift:
--------------------------------------------------------------------------------
1 | #Preview {
2 | CounterView(
3 | store: Store(initialState: CounterFeature.State()) {
4 | CounterFeature()
5 | }
6 | )
7 | }
8 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/01-Essentials/01-YourFirstFeature/01-01-03-code-0001.swift:
--------------------------------------------------------------------------------
1 | import SwiftUI
2 |
3 | @main
4 | struct MyApp: App {
5 | var body: some Scene {
6 | WindowGroup {
7 | ContentView()
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/01-Essentials/01-YourFirstFeature/01-01-03-code-0002.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 |
4 | @main
5 | struct MyApp: App {
6 | var body: some Scene {
7 | WindowGroup {
8 | CounterView(
9 | store: Store(initialState: CounterFeature.State()) {
10 | CounterFeature()
11 | }
12 | )
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/01-Essentials/01-YourFirstFeature/01-01-03-code-0003.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 |
4 | @main
5 | struct MyApp: App {
6 | static let store = Store(initialState: CounterFeature.State()) {
7 | CounterFeature()
8 | }
9 |
10 | var body: some Scene {
11 | WindowGroup {
12 | CounterView(store: MyApp.store)
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/01-Essentials/01-YourFirstFeature/01-01-03-code-0004.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 |
4 | @main
5 | struct MyApp: App {
6 | static let store = Store(initialState: CounterFeature.State()) {
7 | CounterFeature()
8 | ._printChanges()
9 | }
10 |
11 | var body: some Scene {
12 | WindowGroup {
13 | CounterView(store: MyApp.store)
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/01-Essentials/02-AddingSideEffects/01-02-01-code-0003.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 |
3 | @Reducer
4 | struct CounterFeature {
5 | @ObservableState
6 | struct State {
7 | var count = 0
8 | }
9 |
10 | enum Action {
11 | case decrementButtonTapped
12 | case incrementButtonTapped
13 | }
14 |
15 | var body: some ReducerOf {
16 | Reduce { state, action in
17 | switch action {
18 | case .decrementButtonTapped:
19 | state.count -= 1
20 | return .none
21 |
22 | case .incrementButtonTapped:
23 | state.count += 1
24 | return .none
25 | }
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/01-Essentials/03-TestingYourFeatures/01-03-01-code-0001.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import CounterApp
5 |
6 | @MainActor
7 | struct CounterFeatureTests {
8 | @Test
9 | func basics() async {
10 |
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/01-Essentials/03-TestingYourFeatures/01-03-01-code-0002.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import CounterApp
5 |
6 | @MainActor
7 | struct CounterFeatureTests {
8 | @Test
9 | func basics() async {
10 | let store = TestStore(initialState: CounterFeature.State()) {
11 | CounterFeature()
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/01-Essentials/03-TestingYourFeatures/01-03-01-code-0004.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import CounterApp
5 |
6 | @MainActor
7 | struct CounterFeatureTests {
8 | @Test
9 | func basics() async {
10 | let store = TestStore(initialState: CounterFeature.State()) {
11 | CounterFeature()
12 | }
13 |
14 | await store.send(.incrementButtonTapped)
15 | await store.send(.decrementButtonTapped)
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/01-Essentials/03-TestingYourFeatures/01-03-01-code-0006.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import CounterApp
5 |
6 | @MainActor
7 | struct CounterFeatureTests {
8 | @Test
9 | func basics() async {
10 | let store = TestStore(initialState: CounterFeature.State()) {
11 | CounterFeature()
12 | }
13 |
14 | await store.send(.incrementButtonTapped) {
15 | $0.count = 1
16 | }
17 | await store.send(.decrementButtonTapped) {
18 | $0.count = 0
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/01-Essentials/03-TestingYourFeatures/01-03-02-code-0001-previous.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import CounterApp
5 |
6 | @MainActor
7 | struct CounterFeatureTests {
8 | }
9 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/01-Essentials/03-TestingYourFeatures/01-03-02-code-0001.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import CounterApp
5 |
6 | @MainActor
7 | struct CounterFeatureTests {
8 | @Test
9 | func basics() async {
10 | let store = TestStore(initialState: CounterFeature.State()) {
11 | CounterFeature()
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/01-Essentials/03-TestingYourFeatures/01-03-02-code-0002.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import CounterApp
5 |
6 | @MainActor
7 | struct CounterFeatureTests {
8 | @Test
9 | func timer() async {
10 | let store = TestStore(initialState: CounterFeature.State()) {
11 | CounterFeature()
12 | }
13 |
14 | await store.send(.toggleTimerButtonTapped) {
15 | $0.isTimerRunning = true
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/01-Essentials/03-TestingYourFeatures/01-03-02-code-0003.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import CounterApp
5 |
6 | @MainActor
7 | struct CounterFeatureTests {
8 | @Test
9 | func timer() async {
10 | let store = TestStore(initialState: CounterFeature.State()) {
11 | CounterFeature()
12 | }
13 |
14 | await store.send(.toggleTimerButtonTapped) {
15 | $0.isTimerRunning = true
16 | }
17 | // ❌ An effect returned for this action is still running.
18 | // It must complete before the end of the test. …
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/01-Essentials/03-TestingYourFeatures/01-03-02-code-0004.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import CounterApp
5 |
6 | @MainActor
7 | struct CounterFeatureTests {
8 | @Test
9 | func timer() async {
10 | let store = TestStore(initialState: CounterFeature.State()) {
11 | CounterFeature()
12 | }
13 |
14 | await store.send(.toggleTimerButtonTapped) {
15 | $0.isTimerRunning = true
16 | }
17 | await store.send(.toggleTimerButtonTapped) {
18 | $0.isTimerRunning = false
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/01-Essentials/03-TestingYourFeatures/01-03-02-code-0005.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import CounterApp
5 |
6 | @MainActor
7 | struct CounterFeatureTests {
8 | @Test
9 | func timer() async {
10 | let store = TestStore(initialState: CounterFeature.State()) {
11 | CounterFeature()
12 | }
13 |
14 | await store.send(.toggleTimerButtonTapped) {
15 | $0.isTimerRunning = true
16 | }
17 | await store.receive(\.timerTick) {
18 | $0.count = 1
19 | }
20 | await store.send(.toggleTimerButtonTapped) {
21 | $0.isTimerRunning = false
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/01-Essentials/03-TestingYourFeatures/01-03-02-code-0007.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import CounterApp
5 |
6 | @MainActor
7 | struct CounterFeatureTests {
8 | @Test
9 | func timer() async {
10 | let store = TestStore(initialState: CounterFeature.State()) {
11 | CounterFeature()
12 | }
13 |
14 | await store.send(.toggleTimerButtonTapped) {
15 | $0.isTimerRunning = true
16 | }
17 | await store.receive(\.timerTick, timeout: .seconds(2)) {
18 | $0.count = 1
19 | }
20 | await store.send(.toggleTimerButtonTapped) {
21 | $0.isTimerRunning = false
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/01-Essentials/03-TestingYourFeatures/01-03-02-code-0009.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import CounterApp
5 |
6 | @MainActor
7 | struct CounterFeatureTests {
8 | @Test
9 | func timer() async {
10 | let store = TestStore(initialState: CounterFeature.State()) {
11 | CounterFeature()
12 | }
13 |
14 | await store.send(.toggleTimerButtonTapped) {
15 | $0.isTimerRunning = true
16 | }
17 | await store.receive(\.timerTick, timeout: .seconds(2)) {
18 | $0.count = 1
19 | }
20 | await store.send(.toggleTimerButtonTapped) {
21 | $0.isTimerRunning = false
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/01-Essentials/03-TestingYourFeatures/01-03-03-code-0001-previous.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import CounterApp
5 |
6 | @MainActor
7 | struct CounterFeatureTests {
8 | }
9 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/01-Essentials/03-TestingYourFeatures/01-03-03-code-0001.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import CounterApp
5 |
6 | @MainActor
7 | struct CounterFeatureTests {
8 | @Test
9 | func numberFact() async {
10 | let store = TestStore(initialState: CounterFeature.State()) {
11 | CounterFeature()
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/01-Essentials/03-TestingYourFeatures/01-03-03-code-0002.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import CounterApp
5 |
6 | @MainActor
7 | struct CounterFeatureTests {
8 | @Test
9 | func numberFact() async {
10 | let store = TestStore(initialState: CounterFeature.State()) {
11 | CounterFeature()
12 | }
13 |
14 | await store.send(.factButtonTapped) {
15 | $0.isLoading = true
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/01-Essentials/03-TestingYourFeatures/01-03-03-code-0003.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import CounterApp
5 |
6 | @MainActor
7 | struct CounterFeatureTests {
8 | @Test
9 | func numberFact() async {
10 | let store = TestStore(initialState: CounterFeature.State()) {
11 | CounterFeature()
12 | }
13 |
14 | await store.send(.factButtonTapped) {
15 | $0.isLoading = true
16 | }
17 | // ❌ An effect returned for this action is still running.
18 | // It must complete before the end of the test. …
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/01-Essentials/03-TestingYourFeatures/01-03-03-code-0004.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import CounterApp
5 |
6 | @MainActor
7 | struct CounterFeatureTests {
8 | @Test
9 | func numberFact() async {
10 | let store = TestStore(initialState: CounterFeature.State()) {
11 | CounterFeature()
12 | }
13 |
14 | await store.send(.factButtonTapped) {
15 | $0.isLoading = true
16 | }
17 | await store.receive(\.factResponse, timeout: .seconds(1)) {
18 | $0.isLoading = false
19 | $0.fact = "???"
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/01-Essentials/03-TestingYourFeatures/01-03-04-code-0001.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/01-Essentials/03-TestingYourFeatures/01-03-04-code-0002.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 |
3 | struct NumberFactClient {
4 | var fetch: (Int) async throws -> String
5 | }
6 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/01-Essentials/03-TestingYourFeatures/01-03-04-code-0003.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Foundation
3 |
4 | struct NumberFactClient {
5 | var fetch: (Int) async throws -> String
6 | }
7 |
8 | extension NumberFactClient: DependencyKey {
9 | static let liveValue = Self(
10 | fetch: { number in
11 | let (data, _) = try await URLSession.shared
12 | .data(from: URL(string: "http://numbersapi.com/\(number)")!)
13 | return String(decoding: data, as: UTF8.self)
14 | }
15 | )
16 | }
17 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/01-Essentials/03-TestingYourFeatures/01-03-04-code-0004.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Foundation
3 |
4 | struct NumberFactClient {
5 | var fetch: (Int) async throws -> String
6 | }
7 |
8 | extension NumberFactClient: DependencyKey {
9 | static let liveValue = Self(
10 | fetch: { number in
11 | let (data, _) = try await URLSession.shared
12 | .data(from: URL(string: "http://numbersapi.com/\(number)")!)
13 | return String(decoding: data, as: UTF8.self)
14 | }
15 | )
16 | }
17 |
18 | extension DependencyValues {
19 | var numberFact: NumberFactClient {
20 | get { self[NumberFactClient.self] }
21 | set { self[NumberFactClient.self] = newValue }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/01-Essentials/03-TestingYourFeatures/01-03-04-code-0006-previous.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import CounterApp
5 |
6 | @MainActor
7 | struct CounterFeatureTests {
8 | @Test
9 | func numberFact() async {
10 | let store = TestStore(initialState: CounterFeature.State()) {
11 | CounterFeature()
12 | }
13 |
14 | await store.send(.factButtonTapped) {
15 | $0.isLoading = true
16 | }
17 | await store.receive(\.factResponse, timeout: .seconds(1)) {
18 | $0.isLoading = false
19 | $0.fact = "???"
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/01-Essentials/03-TestingYourFeatures/01-03-04-code-0007.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import CounterApp
5 |
6 | @MainActor
7 | struct CounterFeatureTests {
8 | @Test
9 | func numberFact() async {
10 | let store = TestStore(initialState: CounterFeature.State()) {
11 | CounterFeature()
12 | } withDependencies: {
13 | $0.numberFact.fetch = { "\($0) is a good number." }
14 | }
15 |
16 | await store.send(.factButtonTapped) {
17 | $0.isLoading = true
18 | }
19 | await store.receive(\.factResponse, timeout: .seconds(1)) {
20 | $0.isLoading = false
21 | $0.fact = "???"
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/01-Essentials/03-TestingYourFeatures/01-03-04-code-0008.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import CounterApp
5 |
6 | @MainActor
7 | struct CounterFeatureTests {
8 | @Test
9 | func numberFact() async {
10 | let store = TestStore(initialState: CounterFeature.State()) {
11 | CounterFeature()
12 | } withDependencies: {
13 | $0.numberFact.fetch = { "\($0) is a good number." }
14 | }
15 |
16 | await store.send(.factButtonTapped) {
17 | $0.isLoading = true
18 | }
19 | await store.receive(\.factResponse) {
20 | $0.isLoading = false
21 | $0.fact = "0 is a good number."
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/01-Essentials/04-ComposingFeatures/01-04-01-code-0001.swift:
--------------------------------------------------------------------------------
1 | import SwiftUI
2 |
3 | struct AppView: View {
4 | var body: some View {
5 | TabView {
6 |
7 | }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/01-Essentials/04-ComposingFeatures/01-04-01-code-0002.swift:
--------------------------------------------------------------------------------
1 | import SwiftUI
2 |
3 | struct AppView: View {
4 | var body: some View {
5 | TabView {
6 | CounterView(store: ???)
7 | .tabItem {
8 | Text("Counter 1")
9 | }
10 |
11 | CounterView(store: ???)
12 | .tabItem {
13 | Text("Counter 2")
14 | }
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/01-Essentials/04-ComposingFeatures/01-04-01-code-0003.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 |
4 | struct AppView: View {
5 | let store1: StoreOf
6 | let store2: StoreOf
7 |
8 | var body: some View {
9 | TabView {
10 | CounterView(store: store1)
11 | .tabItem {
12 | Text("Counter 1")
13 | }
14 |
15 | CounterView(store: store2)
16 | .tabItem {
17 | Text("Counter 2")
18 | }
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/01-Essentials/04-ComposingFeatures/01-04-02-code-0001.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 |
3 | @Reducer
4 | struct AppFeature {
5 |
6 | }
7 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/01-Essentials/04-ComposingFeatures/01-04-02-code-0002.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 |
3 | @Reducer
4 | struct AppFeature {
5 | struct State: Equatable {
6 | var tab1 = CounterFeature.State()
7 | var tab2 = CounterFeature.State()
8 | }
9 | enum Action {
10 | case tab1(CounterFeature.Action)
11 | case tab2(CounterFeature.Action)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/01-Essentials/04-ComposingFeatures/01-04-02-code-0003.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 |
3 | @Reducer
4 | struct AppFeature {
5 | struct State: Equatable {
6 | var tab1 = CounterFeature.State()
7 | var tab2 = CounterFeature.State()
8 | }
9 | enum Action {
10 | case tab1(CounterFeature.Action)
11 | case tab2(CounterFeature.Action)
12 | }
13 | var body: some ReducerOf {
14 | Reduce { state, action in
15 | // Core logic of the app feature
16 | return .none
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/01-Essentials/04-ComposingFeatures/01-04-02-code-0004.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 |
3 | @Reducer
4 | struct AppFeature {
5 | struct State: Equatable {
6 | var tab1 = CounterFeature.State()
7 | var tab2 = CounterFeature.State()
8 | }
9 | enum Action {
10 | case tab1(CounterFeature.Action)
11 | case tab2(CounterFeature.Action)
12 | }
13 | var body: some ReducerOf {
14 | Scope(state: \.tab1, action: \.tab1) {
15 | CounterFeature()
16 | }
17 | Scope(state: \.tab2, action: \.tab2) {
18 | CounterFeature()
19 | }
20 | Reduce { state, action in
21 | // Core logic of the app feature
22 | return .none
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/01-Essentials/04-ComposingFeatures/01-04-02-code-0005.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import CounterApp
5 |
6 | @MainActor
7 | struct AppFeatureTests {
8 | @Test
9 | func incrementInFirstTab() async {
10 |
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/01-Essentials/04-ComposingFeatures/01-04-02-code-0006.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import CounterApp
5 |
6 | @MainActor
7 | struct AppFeatureTests {
8 | @Test
9 | func incrementInFirstTab() async {
10 | let store = TestStore(initialState: AppFeature.State()) {
11 | AppFeature()
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/01-Essentials/04-ComposingFeatures/01-04-02-code-0007.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import CounterApp
5 |
6 | @MainActor
7 | struct AppFeatureTests {
8 | @Test
9 | func incrementInFirstTab() async {
10 | let store = TestStore(initialState: AppFeature.State()) {
11 | AppFeature()
12 | }
13 |
14 | await store.send(\.tab1.incrementButtonTapped)
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/01-Essentials/04-ComposingFeatures/01-04-02-code-0008.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import CounterApp
5 |
6 | @MainActor
7 | struct AppFeatureTests {
8 | @Test
9 | func incrementInFirstTab() async {
10 | let store = TestStore(initialState: AppFeature.State()) {
11 | AppFeature()
12 | }
13 |
14 | await store.send(\.tab1.incrementButtonTapped) {
15 | $0.tab1.count = 1
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/01-Essentials/04-ComposingFeatures/01-04-03-code-0001-previous.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 |
4 | struct AppView: View {
5 | // let store1: StoreOf
6 | // let store2: StoreOf
7 |
8 | var body: some View {
9 | TabView {
10 | CounterView(store: store1)
11 | .tabItem {
12 | Text("Counter 1")
13 | }
14 |
15 | CounterView(store: store2)
16 | .tabItem {
17 | Text("Counter 2")
18 | }
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/01-Essentials/04-ComposingFeatures/01-04-03-code-0001.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 |
4 | struct AppView: View {
5 | // let store1: StoreOf
6 | // let store2: StoreOf
7 | let store: StoreOf
8 |
9 | var body: some View {
10 | TabView {
11 | CounterView(store: store1)
12 | .tabItem {
13 | Text("Counter 1")
14 | }
15 |
16 | CounterView(store: store2)
17 | .tabItem {
18 | Text("Counter 2")
19 | }
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/01-Essentials/04-ComposingFeatures/01-04-03-code-0002.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 |
4 | struct AppView: View {
5 | let store: StoreOf
6 |
7 | var body: some View {
8 | TabView {
9 | CounterView(store: store.scope(state: \.tab1, action: \.tab1))
10 | .tabItem {
11 | Text("Counter 1")
12 | }
13 |
14 | CounterView(store: store2)
15 | .tabItem {
16 | Text("Counter 2")
17 | }
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/01-Essentials/04-ComposingFeatures/01-04-03-code-0003.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 |
4 | struct AppView: View {
5 | let store: StoreOf
6 |
7 | var body: some View {
8 | TabView {
9 | CounterView(store: store.scope(state: \.tab1, action: \.tab1))
10 | .tabItem {
11 | Text("Counter 1")
12 | }
13 |
14 | CounterView(store: store.scope(state: \.tab2, action: \.tab2))
15 | .tabItem {
16 | Text("Counter 2")
17 | }
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/01-Essentials/04-ComposingFeatures/01-04-03-code-0004.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 |
4 | struct AppView: View {
5 | let store: StoreOf
6 |
7 | var body: some View {
8 | TabView {
9 | CounterView(store: store.scope(state: \.tab1, action: \.tab1))
10 | .tabItem {
11 | Text("Counter 1")
12 | }
13 |
14 | CounterView(store: store.scope(state: \.tab2, action: \.tab2))
15 | .tabItem {
16 | Text("Counter 2")
17 | }
18 | }
19 | }
20 | }
21 |
22 | #Preview {
23 | AppView(
24 | store: Store(initialState: AppFeature.State()) {
25 | AppFeature()
26 | }
27 | )
28 | }
29 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/01-Essentials/04-ComposingFeatures/01-04-03-code-0005-previous.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 |
4 | @main
5 | struct MyApp: App {
6 | static let store = Store(initialState: CounterFeature.State()) {
7 | CounterFeature()
8 | ._printChanges()
9 | }
10 |
11 | var body: some Scene {
12 | WindowGroup {
13 | CounterView(store: MyApp.store)
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/01-Essentials/04-ComposingFeatures/01-04-03-code-0005.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 |
4 | @main
5 | struct MyApp: App {
6 | static let store = Store(initialState: AppFeature.State()) {
7 | AppFeature()
8 | }
9 |
10 | var body: some Scene {
11 | WindowGroup {
12 | AppView(store: MyApp.store)
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/01-YourFirstPresentation/02-01-01-code-0000.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | import ComposableArchitecture
3 |
4 | struct Contact: Equatable, Identifiable {
5 | let id: UUID
6 | var name: String
7 | }
8 |
9 | @Reducer
10 | struct ContactsFeature {
11 | @ObservableState
12 | struct State: Equatable {
13 | var contacts: IdentifiedArrayOf = []
14 | }
15 | enum Action {
16 | case addButtonTapped
17 | }
18 | var body: some ReducerOf {
19 | Reduce { state, action in
20 | switch action {
21 | case .addButtonTapped:
22 | // TODO: Handle action
23 | return .none
24 | }
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/01-YourFirstPresentation/02-01-01-code-0001.swift:
--------------------------------------------------------------------------------
1 | import SwiftUI
2 |
3 | struct ContactsView: View {
4 | let store: StoreOf
5 |
6 | var body: some View {
7 | NavigationStack {
8 | List {
9 | ForEach(store.contacts) { contact in
10 | Text(contact.name)
11 | }
12 | }
13 | .navigationTitle("Contacts")
14 | .toolbar {
15 | ToolbarItem {
16 | Button {
17 | store.send(.addButtonTapped)
18 | } label: {
19 | Image(systemName: "plus")
20 | }
21 | }
22 | }
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/01-YourFirstPresentation/02-01-01-code-0002.swift:
--------------------------------------------------------------------------------
1 | #Preview {
2 | ContactsView(
3 | store: Store(
4 | initialState: ContactsFeature.State(
5 | contacts: [
6 | Contact(id: UUID(), name: "Blob"),
7 | Contact(id: UUID(), name: "Blob Jr"),
8 | Contact(id: UUID(), name: "Blob Sr"),
9 | ]
10 | )
11 | ) {
12 | ContactsFeature()
13 | }
14 | )
15 | }
16 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/01-YourFirstPresentation/02-01-01-code-0003.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 |
3 | @Reducer
4 | struct AddContactFeature {
5 | @ObservableState
6 | struct State: Equatable {
7 | var contact: Contact
8 | }
9 | enum Action {
10 | case cancelButtonTapped
11 | case saveButtonTapped
12 | case setName(String)
13 | }
14 | var body: some ReducerOf {
15 | Reduce { state, action in
16 | switch action {
17 | case .cancelButtonTapped:
18 | return .none
19 |
20 | case .saveButtonTapped:
21 | return .none
22 |
23 | case let .setName(name):
24 | state.contact.name = name
25 | return .none
26 | }
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/01-YourFirstPresentation/02-01-01-code-0004.swift:
--------------------------------------------------------------------------------
1 | import SwiftUI
2 |
3 | struct AddContactView: View {
4 | @Bindable var store: StoreOf
5 | }
6 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/01-YourFirstPresentation/02-01-01-code-0005.swift:
--------------------------------------------------------------------------------
1 | import SwiftUI
2 |
3 | struct AddContactView: View {
4 | @Bindable var store: StoreOf
5 |
6 | var body: some View {
7 | Form {
8 | TextField("Name", text: $store.contact.name.sending(\.setName))
9 | }
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/01-YourFirstPresentation/02-01-01-code-0006.swift:
--------------------------------------------------------------------------------
1 | import SwiftUI
2 |
3 | struct AddContactView: View {
4 | @Bindable var store: StoreOf
5 |
6 | var body: some View {
7 | Form {
8 | TextField("Name", text: $store.contact.name.sending(\.setName))
9 | Button("Save") {
10 | store.send(.saveButtonTapped)
11 | }
12 | }
13 | .toolbar {
14 | ToolbarItem {
15 | Button("Cancel") {
16 | store.send(.cancelButtonTapped)
17 | }
18 | }
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/01-YourFirstPresentation/02-01-01-code-0007.swift:
--------------------------------------------------------------------------------
1 | #Preview {
2 | NavigationStack {
3 | AddContactView(
4 | store: Store(
5 | initialState: AddContactFeature.State(
6 | contact: Contact(
7 | id: UUID(),
8 | name: "Blob"
9 | )
10 | )
11 | ) {
12 | AddContactFeature()
13 | }
14 | )
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/01-YourFirstPresentation/02-01-02-code-0000.swift:
--------------------------------------------------------------------------------
1 | @Reducer
2 | struct ContactsFeature {
3 | @ObservableState
4 | struct State: Equatable {
5 | var contacts: IdentifiedArrayOf = []
6 | }
7 | enum Action {
8 | case addButtonTapped
9 | }
10 | var body: some ReducerOf {
11 | Reduce { state, action in
12 | switch action {
13 | case .addButtonTapped:
14 | // TODO: Handle action
15 | return .none
16 | }
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/01-YourFirstPresentation/02-01-02-code-0001.swift:
--------------------------------------------------------------------------------
1 | @Reducer
2 | struct ContactsFeature {
3 | @ObservableState
4 | struct State: Equatable {
5 | @Presents var addContact: AddContactFeature.State?
6 | var contacts: IdentifiedArrayOf = []
7 | }
8 | enum Action {
9 | case addButtonTapped
10 | }
11 | var body: some ReducerOf {
12 | Reduce { state, action in
13 | switch action {
14 | case .addButtonTapped:
15 | // TODO: Handle action
16 | return .none
17 | }
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/01-YourFirstPresentation/02-01-02-code-0002.swift:
--------------------------------------------------------------------------------
1 | @Reducer
2 | struct ContactsFeature {
3 | @ObservableState
4 | struct State: Equatable {
5 | @Presents var addContact: AddContactFeature.State?
6 | var contacts: IdentifiedArrayOf = []
7 | }
8 | enum Action {
9 | case addButtonTapped
10 | case addContact(PresentationAction)
11 | }
12 | var body: some ReducerOf {
13 | Reduce { state, action in
14 | switch action {
15 | case .addButtonTapped:
16 | // TODO: Handle action
17 | return .none
18 | }
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/01-YourFirstPresentation/02-01-02-code-0003.swift:
--------------------------------------------------------------------------------
1 | @Reducer
2 | struct ContactsFeature {
3 | @ObservableState
4 | struct State: Equatable {
5 | @Presents var addContact: AddContactFeature.State?
6 | var contacts: IdentifiedArrayOf = []
7 | }
8 | enum Action {
9 | case addButtonTapped
10 | case addContact(PresentationAction)
11 | }
12 | var body: some ReducerOf {
13 | Reduce { state, action in
14 | switch action {
15 | case .addButtonTapped:
16 | // TODO: Handle action
17 | return .none
18 |
19 | case .addContact:
20 | return .none
21 | }
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/01-YourFirstPresentation/02-01-02-code-0008.swift:
--------------------------------------------------------------------------------
1 | struct ContactsView: View {
2 | let store: StoreOf
3 |
4 | var body: some View {
5 | NavigationStack {
6 | List {
7 | ForEach(store.contacts) { contact in
8 | Text(contact.name)
9 | }
10 | }
11 | .navigationTitle("Contacts")
12 | .toolbar {
13 | ToolbarItem {
14 | Button {
15 | store.send(.addButtonTapped)
16 | } label: {
17 | Image(systemName: "plus")
18 | }
19 | }
20 | }
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/02-MultipleDestinations/02-02-02-code-0000.swift:
--------------------------------------------------------------------------------
1 | extension ContactsFeature {
2 | @Reducer
3 | enum Destination {
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/02-MultipleDestinations/02-02-02-code-0001.swift:
--------------------------------------------------------------------------------
1 | extension ContactsFeature {
2 | @Reducer
3 | enum Destination {
4 | case addContact(AddContactFeature)
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/02-MultipleDestinations/02-02-02-code-0002.swift:
--------------------------------------------------------------------------------
1 | extension ContactsFeature {
2 | @Reducer
3 | enum Destination {
4 | case addContact(AddContactFeature)
5 | case alert(AlertState)
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/02-MultipleDestinations/02-02-02-code-0004-previous.swift:
--------------------------------------------------------------------------------
1 | extension ContactsFeature {
2 | @Reducer
3 | enum Destination {
4 | case addContact(AddContactFeature)
5 | case alert(AlertState)
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/02-MultipleDestinations/02-02-02-code-0004.swift:
--------------------------------------------------------------------------------
1 | extension ContactsFeature {
2 | @Reducer
3 | enum Destination {
4 | case addContact(AddContactFeature)
5 | case alert(AlertState)
6 | }
7 | }
8 | extension ContactsFeature.Destination.State: Equatable {}
9 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/03-TestingPresentation/02-03-01-code-0000.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import ContactsApp
5 |
6 | @MainActor
7 | struct ContactsFeatureTests {
8 | @Test
9 | func addFlow() async {
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/03-TestingPresentation/02-03-01-code-0001.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import ContactsApp
5 |
6 | @MainActor
7 | struct ContactsFeatureTests {
8 | @Test
9 | func addFlow() async {
10 | let store = TestStore(initialState: ContactsFeature.State()) {
11 | ContactsFeature()
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/03-TestingPresentation/02-03-01-code-0002.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import ContactsApp
5 |
6 | @MainActor
7 | struct ContactsFeatureTests {
8 | @Test
9 | func addFlow() async {
10 | let store = TestStore(initialState: ContactsFeature.State()) {
11 | ContactsFeature()
12 | }
13 |
14 | await store.send(.addButtonTapped) {
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/03-TestingPresentation/02-03-01-code-0003.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import ContactsApp
5 |
6 | @MainActor
7 | struct ContactsFeatureTests {
8 | @Test
9 | func addFlow() async {
10 | let store = TestStore(initialState: ContactsFeature.State()) {
11 | ContactsFeature()
12 | }
13 |
14 | await store.send(.addButtonTapped) {
15 | $0.destination = .addContact(
16 | )
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/03-TestingPresentation/02-03-01-code-0004.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import ContactsApp
5 |
6 | @MainActor
7 | struct ContactsFeatureTests {
8 | @Test
9 | func addFlow() async {
10 | let store = TestStore(initialState: ContactsFeature.State()) {
11 | ContactsFeature()
12 | }
13 |
14 | await store.send(.addButtonTapped) {
15 | $0.destination = .addContact(
16 | AddContactFeature.State(
17 | )
18 | )
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/03-TestingPresentation/02-03-01-code-0005.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import ContactsApp
5 |
6 | @MainActor
7 | struct ContactsFeatureTests {
8 | @Test
9 | func addFlow() async {
10 | let store = TestStore(initialState: ContactsFeature.State()) {
11 | ContactsFeature()
12 | }
13 |
14 | await store.send(.addButtonTapped) {
15 | $0.destination = .addContact(
16 | AddContactFeature.State(
17 | contact: Contact(id: ???, name: "")
18 | )
19 | )
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/03-TestingPresentation/02-03-01-code-0008-previous.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import ContactsApp
5 |
6 | @MainActor
7 | struct ContactsFeatureTests {
8 | @Test
9 | func addFlow() async {
10 | let store = TestStore(initialState: ContactsFeature.State()) {
11 | ContactsFeature()
12 | }
13 |
14 | await store.send(.addButtonTapped) {
15 | $0.destination = .addContact(
16 | AddContactFeature.State(
17 | contact: Contact(id: ???, name: "")
18 | )
19 | )
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/03-TestingPresentation/02-03-01-code-0008.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import ContactsApp
5 |
6 | @MainActor
7 | struct ContactsFeatureTests {
8 | @Test
9 | func addFlow() async {
10 | let store = TestStore(initialState: ContactsFeature.State()) {
11 | ContactsFeature()
12 | } withDependencies: {
13 | $0.uuid = .incrementing
14 | }
15 |
16 | await store.send(.addButtonTapped) {
17 | $0.destination = .addContact(
18 | AddContactFeature.State(
19 | contact: Contact(id: ???, name: "")
20 | )
21 | )
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/03-TestingPresentation/02-03-01-code-0009.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Foundation
3 | import Testing
4 |
5 | @testable import ContactsApp
6 |
7 | @MainActor
8 | struct ContactsFeatureTests {
9 | @Test
10 | func addFlow() async {
11 | let store = TestStore(initialState: ContactsFeature.State()) {
12 | ContactsFeature()
13 | } withDependencies: {
14 | $0.uuid = .incrementing
15 | }
16 |
17 | await store.send(.addButtonTapped) {
18 | $0.destination = .addContact(
19 | AddContactFeature.State(
20 | contact: Contact(id: UUID(0), name: "")
21 | )
22 | )
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/03-TestingPresentation/02-03-02-code-0000.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Foundation
3 | import Testing
4 |
5 | @testable import ContactsApp
6 |
7 | @MainActor
8 | struct ContactsFeatureTests {
9 | @Test
10 | func addFlowNonExhaustive() async {
11 | let store = TestStore(initialState: ContactsFeature.State()) {
12 | ContactsFeature()
13 | } withDependencies: {
14 | $0.uuid = .incrementing
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/03-TestingPresentation/02-03-02-code-0001.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Foundation
3 | import Testing
4 |
5 | @testable import ContactsApp
6 |
7 | @MainActor
8 | struct ContactsFeatureTests {
9 | @Test
10 | func addFlowNonExhaustive() async {
11 | let store = TestStore(initialState: ContactsFeature.State()) {
12 | ContactsFeature()
13 | } withDependencies: {
14 | $0.uuid = .incrementing
15 | }
16 | store.exhaustivity = .off
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/03-TestingPresentation/02-03-02-code-0002.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Foundation
3 | import Testing
4 |
5 | @testable import ContactsApp
6 |
7 | @MainActor
8 | struct ContactsFeatureTests {
9 | @Test
10 | func addFlowNonExhaustive() async {
11 | let store = TestStore(initialState: ContactsFeature.State()) {
12 | ContactsFeature()
13 | } withDependencies: {
14 | $0.uuid = .incrementing
15 | }
16 | store.exhaustivity = .off
17 |
18 | await store.send(.addButtonTapped)
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/03-TestingPresentation/02-03-02-code-0003.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Foundation
3 | import Testing
4 |
5 | @testable import ContactsApp
6 |
7 | @MainActor
8 | struct ContactsFeatureTests {
9 | @Test
10 | func addFlowNonExhaustive() async {
11 | let store = TestStore(initialState: ContactsFeature.State()) {
12 | ContactsFeature()
13 | } withDependencies: {
14 | $0.uuid = .incrementing
15 | }
16 | store.exhaustivity = .off
17 |
18 | await store.send(.addButtonTapped)
19 | await store.send(\.destination.addContact.setName, "Blob Jr.")
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/03-TestingPresentation/02-03-02-code-0004.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Foundation
3 | import Testing
4 |
5 | @testable import ContactsApp
6 |
7 | @MainActor
8 | struct ContactsFeatureTests {
9 | @Test
10 | func addFlowNonExhaustive() async {
11 | let store = TestStore(initialState: ContactsFeature.State()) {
12 | ContactsFeature()
13 | } withDependencies: {
14 | $0.uuid = .incrementing
15 | }
16 | store.exhaustivity = .off
17 |
18 | await store.send(.addButtonTapped)
19 | await store.send(\.destination.addContact.setName, "Blob Jr.")
20 | await store.send(\.destination.addContact.saveButtonTapped)
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/03-TestingPresentation/02-03-02-code-0005.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Foundation
3 | import Testing
4 |
5 | @testable import ContactsApp
6 |
7 | @MainActor
8 | struct ContactsFeatureTests {
9 | @Test
10 | func addFlowNonExhaustive() async {
11 | let store = TestStore(initialState: ContactsFeature.State()) {
12 | ContactsFeature()
13 | } withDependencies: {
14 | $0.uuid = .incrementing
15 | }
16 | store.exhaustivity = .off
17 |
18 | await store.send(.addButtonTapped)
19 | await store.send(\.destination.addContact.setName, "Blob Jr.")
20 | await store.send(\.destination.addContact.saveButtonTapped)
21 | await store.skipReceivedActions()
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/03-TestingPresentation/02-03-03-code-0000.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import ContactsApp
5 |
6 | @MainActor
7 | struct ContactsFeatureTests {
8 | @Test
9 | func deleteContact() async {
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/03-TestingPresentation/02-03-03-code-0001.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Testing
3 |
4 | @testable import ContactsApp
5 |
6 | @MainActor
7 | struct ContactsFeatureTests {
8 | @Test
9 | func deleteContact() async {
10 | let store = TestStore(initialState: ContactsFeature.State()) {
11 | ContactsFeature()
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/03-TestingPresentation/02-03-03-code-0002.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Foundation
3 | import Testing
4 |
5 | @testable import ContactsApp
6 |
7 | @MainActor
8 | struct ContactsFeatureTests {
9 | @Test
10 | func deleteContact() async {
11 | let store = TestStore(initialState: ContactsFeature.State()) {
12 | initialState: ContactsFeature.State(
13 | contacts: [
14 | Contact(id: UUID(0), name: "Blob"),
15 | Contact(id: UUID(1), name: "Blob Jr."),
16 | ]
17 | )
18 | ) {
19 | ContactsFeature()
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/03-TestingPresentation/02-03-03-code-0003.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Foundation
3 | import Testing
4 |
5 | @testable import ContactsApp
6 |
7 | @MainActor
8 | struct ContactsFeatureTests {
9 | @Test
10 | func deleteContact() async {
11 | let store = TestStore(
12 | initialState: ContactsFeature.State(
13 | contacts: [
14 | Contact(id: UUID(0), name: "Blob"),
15 | Contact(id: UUID(1), name: "Blob Jr."),
16 | ]
17 | )
18 | ) {
19 | ContactsFeature()
20 | }
21 |
22 | await store.send(.deleteButtonTapped(id: UUID(1))) {
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/03-TestingPresentation/02-03-03-code-0004.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Foundation
3 | import Testing
4 |
5 | @testable import ContactsApp
6 |
7 | @MainActor
8 | struct ContactsFeatureTests {
9 | @Test
10 | func deleteContact() async {
11 | let store = TestStore(
12 | initialState: ContactsFeature.State(
13 | contacts: [
14 | Contact(id: UUID(0), name: "Blob"),
15 | Contact(id: UUID(1), name: "Blob Jr."),
16 | ]
17 | )
18 | ) {
19 | ContactsFeature()
20 | }
21 |
22 | await store.send(.deleteButtonTapped(id: UUID(1))) {
23 | $0.destination = .alert(
24 | )
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/03-TestingPresentation/02-03-03-code-0006.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 |
3 | extension AlertState where Action == ContactsFeature.Action.Alert {
4 | static func deleteConfirmation(id: UUID) -> Self {
5 | Self {
6 | TextState("Are you sure?")
7 | } actions: {
8 | ButtonState(role: .destructive, action: .confirmDeletion(id: id)) {
9 | TextState("Delete")
10 | }
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/03-TestingPresentation/02-03-03-code-0008.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import Foundation
3 | import Testing
4 |
5 | @testable import ContactsApp
6 |
7 | @MainActor
8 | struct ContactsFeatureTests {
9 | @Test
10 | func deleteContact() async {
11 | let store = TestStore(
12 | initialState: ContactsFeature.State(
13 | contacts: [
14 | Contact(id: UUID(0), name: "Blob"),
15 | Contact(id: UUID(1), name: "Blob Jr."),
16 | ]
17 | )
18 | ) {
19 | ContactsFeature()
20 | }
21 |
22 | await store.send(.deleteButtonTapped(id: UUID(1))) {
23 | $0.destination = .alert(.deleteConfirmation(id: UUID(1)))
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/04-NavigationStacks/02-04-01-code-0000.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 |
3 | @Reducer
4 | struct ContactDetailFeature {
5 | }
6 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/04-NavigationStacks/02-04-01-code-0001.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 |
3 | @Reducer
4 | struct ContactDetailFeature {
5 | @ObservableState
6 | struct State: Equatable {
7 | let contact: Contact
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/04-NavigationStacks/02-04-01-code-0002.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 |
3 | @Reducer
4 | struct ContactDetailFeature {
5 | @ObservableState
6 | struct State: Equatable {
7 | let contact: Contact
8 | }
9 | enum Action {
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/04-NavigationStacks/02-04-01-code-0003.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 |
3 | @Reducer
4 | struct ContactDetailFeature {
5 | @ObservableState
6 | struct State: Equatable {
7 | let contact: Contact
8 | }
9 | enum Action {
10 | }
11 | var body: some ReducerOf {
12 | Reduce { state, action in
13 | switch action {
14 | }
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/04-NavigationStacks/02-04-01-code-0004.swift:
--------------------------------------------------------------------------------
1 | import SwiftUI
2 |
3 | struct ContactDetailView: View {
4 | var body: some View {
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/04-NavigationStacks/02-04-01-code-0005.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 |
4 | struct ContactDetailView: View {
5 | let store: StoreOf
6 |
7 | var body: some View {
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/04-NavigationStacks/02-04-01-code-0006.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 |
4 | struct ContactDetailView: View {
5 | let store: StoreOf
6 |
7 | var body: some View {
8 | Form {
9 | }
10 | .navigationTitle(Text(store.contact.name))
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/04-NavigationStacks/02-04-01-code-0007.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 |
4 | struct ContactDetailView: View {
5 | let store: StoreOf
6 |
7 | var body: some View {
8 | Form {
9 | }
10 | .navigationTitle(Text(store.contact.name))
11 | }
12 | }
13 |
14 | #Preview {
15 | NavigationStack {
16 | ContactDetailView(
17 | store: Store(
18 | initialState: ContactDetailFeature.State(
19 | contact: Contact(id: UUID(), name: "Blob")
20 | )
21 | ) {
22 | ContactDetailFeature()
23 | }
24 | )
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/04-NavigationStacks/02-04-03-code-0000-previous.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 |
3 | @Reducer
4 | struct ContactDetailFeature {
5 | @ObservableState
6 | struct State: Equatable {
7 | let contact: Contact
8 | }
9 | enum Action {
10 | }
11 | var body: some ReducerOf {
12 | Reduce { state, action in
13 | switch action {
14 | }
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/04-NavigationStacks/02-04-03-code-0000.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 |
3 | @Reducer
4 | struct ContactDetailFeature {
5 | @ObservableState
6 | struct State: Equatable {
7 | @Presents var alert: AlertState?
8 | let contact: Contact
9 | }
10 | enum Action {
11 | }
12 | var body: some ReducerOf {
13 | Reduce { state, action in
14 | switch action {
15 | }
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/04-NavigationStacks/02-04-03-code-0001.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 |
3 | @Reducer
4 | struct ContactDetailFeature {
5 | @ObservableState
6 | struct State: Equatable {
7 | @Presents var alert: AlertState?
8 | let contact: Contact
9 | }
10 | enum Action {
11 | case alert(PresentationAction)
12 | case delegate(Delegate)
13 | case deleteButtonTapped
14 | enum Alert {
15 | case confirmDeletion
16 | }
17 | enum Delegate {
18 | case confirmDeletion
19 | }
20 | }
21 | var body: some ReducerOf {
22 | Reduce { state, action in
23 | switch action {
24 | }
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/04-NavigationStacks/02-04-03-code-0003-previous.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 | import SwiftUI
3 |
4 | struct ContactDetailView: View {
5 | let store: StoreOf
6 |
7 | var body: some View {
8 | Form {
9 | }
10 | .navigationTitle(Text(store.contact.name))
11 | }
12 | }
13 |
14 | #Preview {
15 | NavigationStack {
16 | ContactDetailView(
17 | store: Store(
18 | initialState: ContactDetailFeature.State(
19 | contact: Contact(id: UUID(), name: "Blob")
20 | )
21 | ) {
22 | ContactDetailFeature()
23 | }
24 | )
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/chapter1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/chapter1.png
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/chapter2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/chapter2.png
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/chapter3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/chapter3.png
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/chapter4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/chapter4.png
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/chapter5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/chapter5.png
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/chapter6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/chapter6.png
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/chapter7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/chapter7.png
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/chapter8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pointfreeco/swift-composable-architecture/49f03230076ca964e0c6a4a676e38b6d3ea64c3a/Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/chapter8.png
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Internal/AreOrderedSetsDuplicates.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | import OrderedCollections
3 |
4 | @inlinable
5 | func areOrderedSetsDuplicates(_ lhs: OrderedSet, _ rhs: OrderedSet) -> Bool {
6 | guard lhs.count == rhs.count
7 | else { return false }
8 |
9 | return withUnsafePointer(to: lhs) { lhsPointer in
10 | withUnsafePointer(to: rhs) { rhsPointer in
11 | memcmp(lhsPointer, rhsPointer, MemoryLayout>.size) == 0 || lhs == rhs
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Internal/Box.swift:
--------------------------------------------------------------------------------
1 | final class Box {
2 | var wrappedValue: Wrapped
3 |
4 | init(wrappedValue: Wrapped) {
5 | self.wrappedValue = wrappedValue
6 | }
7 |
8 | var boxedValue: Wrapped {
9 | _read { yield self.wrappedValue }
10 | _modify { yield &self.wrappedValue }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Internal/Debug.swift:
--------------------------------------------------------------------------------
1 | import CustomDump
2 | import Foundation
3 |
4 | extension String {
5 | @usableFromInline
6 | func indent(by indent: Int) -> String {
7 | let indentation = String(repeating: " ", count: indent)
8 | return indentation + self.replacingOccurrences(of: "\n", with: "\n\(indentation)")
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Internal/Exports.swift:
--------------------------------------------------------------------------------
1 | @_exported import CasePaths
2 | @_exported import Clocks
3 | @_exported import CombineSchedulers
4 | @_exported import ConcurrencyExtras
5 | @_exported import CustomDump
6 | @_exported import Dependencies
7 | @_exported import DependenciesMacros
8 | @_exported import IdentifiedCollections
9 | @_exported import Observation
10 | @_exported import Perception
11 | @_exported import Sharing
12 | @_exported import SwiftUINavigation
13 | @_exported import UIKitNavigation
14 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Internal/Locking.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | extension UnsafeMutablePointer {
4 | @inlinable @discardableResult
5 | func sync(_ work: () -> R) -> R {
6 | os_unfair_lock_lock(self)
7 | defer { os_unfair_lock_unlock(self) }
8 | return work()
9 | }
10 |
11 | func lock() {
12 | os_unfair_lock_lock(self)
13 | }
14 |
15 | func unlock() {
16 | os_unfair_lock_unlock(self)
17 | }
18 | }
19 |
20 | extension NSRecursiveLock {
21 | @inlinable @discardableResult
22 | @_spi(Internals) public func sync(work: () -> R) -> R {
23 | self.lock()
24 | defer { self.unlock() }
25 | return work()
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Internal/OpenExistential.swift:
--------------------------------------------------------------------------------
1 | // MARK: Equatable
2 |
3 | func _isEqual(_ lhs: Any, _ rhs: Any) -> Bool? {
4 | (lhs as? any Equatable)?.isEqual(other: rhs)
5 | }
6 |
7 | extension Equatable {
8 | fileprivate func isEqual(other: Any) -> Bool {
9 | self == other as? Self
10 | }
11 | }
12 |
13 | // MARK: Identifiable
14 |
15 | func _identifiableID(_ value: Any) -> AnyHashable? {
16 | func open(_ value: some Identifiable) -> AnyHashable {
17 | value.id
18 | }
19 | guard let value = value as? any Identifiable else { return nil }
20 | return open(value)
21 | }
22 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Internal/ReturningLastNonNilValue.swift:
--------------------------------------------------------------------------------
1 | // Creates a memoized cache that always returns the last non-`nil` value.
2 | //
3 | // Useful for preserving a presented UI during the programmatic dismissal of sheets and other forms
4 | // of navigation, where setting state to `nil` drives dismissal.
5 | func returningLastNonNilValue(_ f: @escaping (A) -> B?) -> (A) -> B? {
6 | var lastWrapped: B?
7 | return { wrapped in
8 | lastWrapped = f(wrapped) ?? lastWrapped
9 | return lastWrapped
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Internal/RuntimeWarnings.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | import IssueReporting
3 |
4 | extension Notification.Name {
5 | @_documentation(visibility: private)
6 | @available(*, deprecated, renamed: "_runtimeWarning")
7 | public static let runtimeWarning = Self("ComposableArchitecture.runtimeWarning")
8 |
9 | /// A notification that is posted when a runtime warning is emitted.
10 | public static let _runtimeWarning = Self("ComposableArchitecture.runtimeWarning")
11 | }
12 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Reducer/Reducers/EmptyReducer.swift:
--------------------------------------------------------------------------------
1 | /// A reducer that does nothing.
2 | ///
3 | /// While not very useful on its own, `EmptyReducer` can be used as a placeholder in APIs that hold
4 | /// reducers.
5 | public struct EmptyReducer: Reducer {
6 | /// Initializes a reducer that does nothing.
7 | @inlinable
8 | public init() {
9 | self.init(internal: ())
10 | }
11 |
12 | @usableFromInline
13 | init(internal: Void) {}
14 |
15 | @inlinable
16 | public func reduce(into _: inout State, action _: Action) -> Effect {
17 | .none
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Reducer/Reducers/Optional.swift:
--------------------------------------------------------------------------------
1 | extension Optional: Reducer where Wrapped: Reducer {
2 | @inlinable
3 | public func reduce(
4 | into state: inout Wrapped.State, action: Wrapped.Action
5 | ) -> Effect {
6 | switch self {
7 | case let .some(wrapped):
8 | return wrapped.reduce(into: &state, action: action)
9 | case .none:
10 | return .none
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitecture/Resources/PrivacyInfo.xcprivacy:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | NSPrivacyCollectedDataTypes
6 |
7 | NSPrivacyAccessedAPITypes
8 |
9 |
10 | NSPrivacyAccessedAPIType
11 | NSPrivacyAccessedAPICategoryUserDefaults
12 | NSPrivacyAccessedAPITypeReasons
13 |
14 | C56D.1
15 |
16 |
17 |
18 | NSPrivacyTrackingDomains
19 |
20 | NSPrivacyTracking
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/Sources/ComposableArchitectureMacros/Plugins.swift:
--------------------------------------------------------------------------------
1 | import SwiftCompilerPlugin
2 | import SwiftSyntaxMacros
3 |
4 | @main
5 | struct MacrosPlugin: CompilerPlugin {
6 | let providingMacros: [any Macro.Type] = [
7 | ObservableStateMacro.self,
8 | ObservationStateTrackedMacro.self,
9 | ObservationStateIgnoredMacro.self,
10 | PresentsMacro.self,
11 | ReducerMacro.self,
12 | ReducerCaseEphemeralMacro.self,
13 | ReducerCaseIgnoredMacro.self,
14 | ViewActionMacro.self,
15 | ]
16 | }
17 |
--------------------------------------------------------------------------------
/Tests/ComposableArchitectureMacrosTests/MacroBaseTestCase.swift:
--------------------------------------------------------------------------------
1 | #if canImport(ComposableArchitectureMacros)
2 | import ComposableArchitectureMacros
3 | import MacroTesting
4 | import SwiftSyntaxMacros
5 | import SwiftSyntaxMacrosTestSupport
6 | import XCTest
7 |
8 | class MacroBaseTestCase: XCTestCase {
9 | override func invokeTest() {
10 | MacroTesting.withMacroTesting(
11 | //isRecording: true,
12 | macros: [
13 | ObservableStateMacro.self,
14 | ObservationStateTrackedMacro.self,
15 | ObservationStateIgnoredMacro.self,
16 | PresentsMacro.self,
17 | ViewActionMacro.self,
18 | ]
19 | ) {
20 | super.invokeTest()
21 | }
22 | }
23 | }
24 | #endif
25 |
--------------------------------------------------------------------------------
/Tests/ComposableArchitectureTests/Internal/BaseTCATestCase.swift:
--------------------------------------------------------------------------------
1 | @_spi(Internals) @_spi(Logging) import ComposableArchitecture
2 | import XCTest
3 |
4 | class BaseTCATestCase: XCTestCase {
5 | override func tearDown() async throws {
6 | try await super.tearDown()
7 | let description = "\(self)"
8 | _cancellationCancellables.withValue {
9 | XCTAssertEqual($0.count, 0, description)
10 | $0.removeAll()
11 | }
12 | await MainActor.run {
13 | Logger.shared.isEnabled = false
14 | Logger.shared.clear()
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Tests/ComposableArchitectureTests/Internal/TestHelpers.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 |
3 | @_transparent
4 | @available(
5 | *,
6 | deprecated,
7 | message: "This is a test that currently fails but should not in the future."
8 | )
9 | func XCTTODO(_ message: String) {
10 | XCTExpectFailure(message)
11 | }
12 |
--------------------------------------------------------------------------------
/Tests/ComposableArchitectureTests/ObservableStateEnumMacroTests.swift:
--------------------------------------------------------------------------------
1 | import ComposableArchitecture
2 |
3 | private enum TestObservableEnum_CompilerDirective {
4 | @Reducer
5 | struct ChildFeature {}
6 | @ObservableState
7 | public enum State {
8 | case child(ChildFeature.State)
9 | #if os(macOS)
10 | case mac(ChildFeature.State)
11 | #elseif os(tvOS)
12 | case tv(ChildFeature.State)
13 | #endif
14 | #if DEBUG
15 | #if INNER
16 | case inner(ChildFeature.State)
17 | #endif
18 | #endif
19 | }
20 | }
21 |
--------------------------------------------------------------------------------