### Setup AtomRoot in SwiftUI App Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md Initialize AtomRoot as the root container for descendant views to access atoms throughout the application. AtomRoot provides the store that enables atom access from anywhere while maintaining testability. ```swift @main struct ExampleApp: App { var body: some Scene { WindowGroup { AtomRoot { ExampleView() } } } } ``` -------------------------------- ### Define Testable Atom with Mock Protocol Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md Create a protocol-based atom definition with a concrete implementation and mock class for testing. This example demonstrates setting up an APIClientAtom that can be overridden with a MockAPIClient in tests, and a FetchBookAtom that depends on the API client atom. ```swift struct Book: Equatable { var title: String var isbn: String } protocol APIClientProtocol { func fetchBook(isbn: String) async throws -> Book } struct APIClient: APIClientProtocol { func fetchBook(isbn: String) async throws -> Book { ... // Networking logic. } } class MockAPIClient: APIClientProtocol { var response: Book? func fetchBook(isbn: String) async throws -> Book { guard let response else { throw URLError(.unknown) } return response } } struct APIClientAtom: ValueAtom, Hashable { func value(context: Context) -> any APIClientProtocol { APIClient() } } struct FetchBookAtom: ThrowingTaskAtom, Hashable { let isbn: String func value(context: Context) async throws -> Book { let api = context.watch(APIClientAtom()) return try await api.fetchBook(isbn: isbn) } } ``` -------------------------------- ### Swift Atom Transaction Context for Atom Initialization Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md Illustrates the use of AtomTransactionContext within atom definitions to manage dependencies and initialize atom values. This example shows how to watch for other atoms and configure objects like CLLocationManager with delegates. ```swift final class LocationManagerDelegate: NSObject, CLLocationManagerDelegate { ... } struct LocationManagerDelegateAtom: ValueAtom, Hashable { func value(context: Context) -> LocationManagerDelegate { LocationManagerDelegate() } } struct LocationManagerAtom: ValueAtom, Hashable { func value(context: Context) -> any LocationManagerProtocol { let delegate = context.watch(LocationManagerDelegateAtom()) let manager = CLLocationManager() manager.delegate = delegate return manager } } ``` -------------------------------- ### Convert TaskAtom to AsyncPhase in SwiftUI Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md Demonstrates converting a ThrowingTaskAtom into AsyncPhase for consuming asynchronous results with loading, success, and failure states. The example uses @Watch property wrapper to bind the weather phase to a view and switch on its states. ```swift struct FetchWeatherAtom: ThrowingTaskAtom, Hashable { func value(context: Context) async throws -> Weather { try await fetchWeather() } } struct WeatherReportView: View { @Watch(FetchWeatherAtom().phase) var weatherPhase // : AsyncPhase var body: some View { switch weatherPhase { case .suspending: Text("Loading.") case .success(let weather): Text("It's \(weather.description) now!") case .failure: Text("Failed to get weather data.") } } } ``` -------------------------------- ### Scoped Atom Example in SwiftUI Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md Demonstrates how to use Scoped atoms with AtomScope to prevent state sharing between different scopes. Each TextInputView within its own AtomScope will have independent TextInputAtom state. ```swift struct TextInputAtom: StateAtom, Scoped, Hashable { func defaultValue(context: Context) -> String { "" } } struct TextInputView: View { @Watch(TextInputAtom()) ... } VStack { // The following two TextInputView don't share TextInputAtom state. AtomScope { TextInputView() } AtomScope { TextInputView() } } ``` -------------------------------- ### Context API - Watch Atom Value with Updates Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md Gets an atom value and starts watching for updates. This is used within views or other atoms to reactively track changes to atom state. ```swift await context.watch(FetchMoviesAtom()) ``` -------------------------------- ### SwiftUI Atom Management with AtomViewContext Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md Demonstrates the usage of AtomViewContext to interact with atom states in SwiftUI. It shows how to watch for atom changes, get bindings, refresh atoms, and perform operations like reading, setting, resetting, and taking snapshots of atom values. Requires the swiftui-atom-properties library. ```swift struct SearchQueryAtom: StateAtom, Hashable { func defaultValue(context: Context) -> String { "" } } struct FetchBooksAtom: ThrowingTaskAtom, Hashable { func value(context: Context) async throws -> [Book] { let query = context.watch(SearchQueryAtom()) return try await fetchBooks(query: query) } } struct BooksView: View { @ViewContext var context: AtomViewContext var body: some View { // watch let booksTask = context.watch(FetchBooksAtom()) // Task<[Book], any Error> // binding let searchQuery = context.binding(SearchQueryAtom()) // Binding List { Suspense(booksTask) { books in ForEach(books, id: \.isbn) { book in Text("\(book.title): \(book.isbn)") } } } .searchable(text: searchQuery) .refreshable { // refresh await context.refresh(FetchBooksAtom()) } .toolbar { ToolbarItem(placement: .bottomBar) { HStack { Button("Reset") { // reset context.reset(SearchQueryAtom()) } Button("All") { // set context.set("All", for: SearchQueryAtom()) } Button("Space") { // subscript context[SearchQueryAtom()].append(" ") } Button("Print") { // read let query = context.read(SearchQueryAtom()) print(query) } Button("Snapshot") { // snapshot let snapshot = context.snapshot() print(snapshot) } } } } } } ``` -------------------------------- ### Share Atom State Across SwiftUI Views Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md This example illustrates sharing atom state across different SwiftUI views without explicit prop drilling. The CounterView uses the @Watch property wrapper to read the count from CounterAtom. This allows multiple views to access and react to the same state managed by the atom, simplifying state management in complex UIs. ```swift struct CounterView: View { @Watch(CounterAtom()) var count var body: some View { VStack { Text("Count: \(count)") CountStepper() } } } ``` -------------------------------- ### Get Snapshot of Dependency Graph with @ViewContext Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md Obtain a snapshot of the atom dependency graph on demand using the @ViewContext property. This is useful for analyzing dependencies and their usage. It requires the Atom library to be set up in the view hierarchy. ```swift @ViewContext var context var debugButton: some View { Button("Dump dependency graph") { let snapshot = context.snapshot() print(snapshot.graphDescription()) } } ``` -------------------------------- ### Custom Atom Effect with Timer in SwiftUI Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md Demonstrates creating a custom AtomEffect, CountTimerEffect, that manages a Timer. This effect handles initialization, updates, and release, including starting a timer on initialization and invalidating it on release. ```swift struct CounterAtom: StateAtom, Hashable { func defaultValue(context: Context) -> Int { 0 } func effect(context: CurrentContext) -> some AtomEffect { CountTimerEffect() } } final class CountTimerEffect: AtomEffect { private var timer: Timer? func initialized(context: Context) { timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { _ in context[CounterAtom()] += 1 } } func updated(context: Context) { print("Count: \(context.read(CounterAtom()))") } func released(context: Context) { timer?.invalidate() timer = nil } } ``` -------------------------------- ### Define StateAtom with Custom Key Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md Create a StateAtom with a custom key property to associate state with unique identifiers. This example demonstrates a UserNameAtom that stores mutable string data keyed by userID, with automatic key generation for Hashable conformance. ```swift struct UserNameAtom: StateAtom { let userID: Int var key: Int { userID } func defaultValue(context: Context) -> String { "Robert" } } ``` -------------------------------- ### Context API - Read Atom Value Without Watching Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md Gets an atom value without establishing a watch on it. Useful for one-time value retrieval without reactive updates. ```swift context.read(CounterAtom()) ``` -------------------------------- ### Get Previous Atom Value in SwiftUI Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md Provides the previous value of an atom, useful for tracking changes or comparing states. Compatible with all atom types. The output is an optional of the atom's value type. ```swift struct CounterAtom: StateAtom, Hashable { func defaultValue(context: Context) -> Int { 0 } } struct CounterView: View { @WatchState(CounterAtom()) var currentValue @Watch(CounterAtom().previous) var previousValue var body: some View { VStack { Text("Current: \(currentValue)") Text("Previous: \(previousValue ?? 0)") Button("Increment") { currentValue += 1 } } } } ``` -------------------------------- ### Declare Primitive Atoms in Swift Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md This snippet shows how to declare a primitive atom named CounterAtom conforming to StateAtom and Hashable protocols. It defines the default value for the atom, which is an integer starting at 0. This is a fundamental step in setting up state management with SwiftUI Atom Properties. ```swift struct CounterAtom: StateAtom, Hashable { func defaultValue(context: Context) -> Int { 0 } } ``` -------------------------------- ### Get Latest Matching Atom Value in SwiftUI Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md Retrieves the latest atom value that satisfies a given condition. This is useful for maintaining the last valid state. Compatible with all atom types, outputting an optional value. ```swift struct Item { let id: Int let isValid: Bool } struct ItemAtom: StateAtom, Hashable { func defaultValue(context: Context) -> Item { Item(id: 0, isValid: false) } } struct ExampleView: View { @Watch(ItemAtom()) var currentItem @Watch(ItemAtom().latest(\Item.isValid)) // Corrected key path syntax var latestValidItem var body: some View { VStack { Text("Current ID: \(currentItem.id)") Text("Latest Valid ID: \(latestValidItem?.id ?? 0)") } } } ``` -------------------------------- ### Initialize AtomRoot in SwiftUI App Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md Sets up the main structure of the SwiftUI application and initializes the AtomRoot, which is required for all views that use atoms. It's recommended to place it directly under WindowGroup. ```swift @main struct TodoApp: App { var body: some Scene { WindowGroup { AtomRoot { TodoList() } } } } ``` -------------------------------- ### Swift Package Repository URL Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md The GitHub repository URL for the swiftui-atom-properties package. Use this URL when adding package dependencies through Xcode or in your Package.swift manifest file. ```text https://github.com/ra1028/swiftui-atom-properties ``` -------------------------------- ### Implement Todo Creation View Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md Develops `TodoCreator`, a SwiftUI `View` that allows users to add new todo items. It uses `@WatchState` to bind to `TodosAtom` for updating the list and includes a `TextField` and a `Button` for input and submission. ```swift struct TodoCreator: View { @WatchState(TodosAtom()) var todos @State var text = "" var body: some View { HStack { TextField("Enter your todo", text: $text) Button("Add") { todos.append(Todo(id: UUID(), text: text, isCompleted: false)) text = "" } } } } ``` -------------------------------- ### Dynamically Initiate Atom Families with Explicit Keys Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md This snippet demonstrates how to create a custom atom that fetches user data based on a dynamic ID. It shows how to explicitly define a `key` for the atom, allowing external parameters to be passed, which is useful for scenarios like fetching data from a server based on a user ID. The `FetchUserAtom` conforms to `ThrowingTaskAtom` and is used within a `UserView` that suspends until the data is available. ```swift struct FetchUserAtom: ThrowingTaskAtom { let id: Int // This atom can also conforms to `Hashable` in this case, // but this example specifies the key explicitly. var key: Int { id } func value(context: Context) async throws -> Value { try await fetchUser(id: id) } } struct UserView: View { let id: Int @ViewContext var context var body: some View { let task = context.watch(FetchUserAtom(id: id)) Suspense(task) { user in VStack { Text("Name: (user.name)") Text("Age: (user.age)") } } } } ``` -------------------------------- ### Implement Todo Item View with Editing Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md Develops `TodoItem`, a SwiftUI `View` for displaying and editing individual todo items. It uses `@WatchState` to access and modify the global `TodosAtom` and incorporates a `Toggle` for completion status and a `TextField` for editing the text, with changes persisted to the atom. ```swift struct TodoItem: View { @WatchState(TodosAtom()) var allTodos @State var text: String @State var isCompleted: Bool let todo: Todo init(todo: Todo) { self.todo = todo self._text = State(initialValue: todo.text) self._isCompleted = State(initialValue: todo.isCompleted) } var index: Int { allTodos.firstIndex { $0.id == todo.id }! } var body: some View { Toggle(isOn: $isCompleted) { TextField("Todo", text: $text) { allTodos[index].text = text } } .onChange(of: isCompleted) { isCompleted in allTodos[index].isCompleted = isCompleted } } } ``` -------------------------------- ### Test Atom Fetching with Mock APIClient in SwiftUI Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md Demonstrates how to test atom behavior by overriding a real API client with a mock implementation using `AtomTestContext`. This allows for isolated testing of atom logic, such as fetching data, without relying on actual network requests. The `override` method on `AtomTestContext` is crucial for dependency injection during testing. ```swift protocol APIClientProtocol { func fetchMusics() async throws -> [Music] } struct APIClient: APIClientProtocol { ... } struct MockAPIClient: APIClientProtocol { ... } struct APIClientAtom: ValueAtom, Hashable { func value(context: Context) -> any APIClientProtocol { APIClient() } } struct FetchMusicsAtom: ThrowingTaskAtom, Hashable { func value(context: Context) async throws -> [Music] { let api = context.watch(APIClientAtom()) return try await api.fetchMusics() } } @MainActor class FetchMusicsTests: XCTestCase { func testFetchMusicsAtom() async throws { let context = AtomTestContext() context.override(APIClientAtom()) { _ in MockAPIClient() } let musics = try await context.watch(FetchMusicsAtom()).value XCTAssertTrue(musics.isEmpty) } } ``` -------------------------------- ### Dependency Graph Visualization in DOT Language Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md Generate a string representation of the atom dependency graph in the DOT language, which can be processed by Graphviz to create visual diagrams. This aids in understanding complex dependencies and data flow within the application. ```dot digraph { node [shape=box] "FilterAtom" "FilterAtom" -> "TodoApp/FilterPicker.swift" [label="line:3"] "FilterAtom" -> "FilteredTodosAtom" "TodosAtom" "TodosAtom" -> "FilteredTodosAtom" "FilteredTodosAtom" "FilteredTodosAtom" -> "TodoApp/TodoList.swift" [label="line:5"] "TodoApp/TodoList.swift" [style=filled] "TodoApp/FilterPicker.swift" [style=filled] } ``` -------------------------------- ### Assemble Todo List View Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md Constructs the main `TodoList` view, which orchestrates the other components. It uses `@Watch` to observe the `FilteredTodosAtom` for displaying the list of todos and includes the `TodoCreator` and `TodoFilters` views. ```swift struct TodoList: View { @Watch(FilteredTodosAtom()) var filteredTodos var body: some View { List { TodoCreator() TodoFilters() ForEach(filteredTodos, id: \.id) { todo in TodoItem(todo: todo) } } } } ``` -------------------------------- ### Override Atoms for Static SwiftUI Previews Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md Configure SwiftUI previews by ensuring an AtomRoot exists in the ancestor hierarchy and using the .override modifier to inject stub implementations for atoms. This allows for isolated testing and display of UI components without live data. ```swift struct NewsList_Preview: PreviewProvider { static var previews: some View { AtomRoot { NewsList() } .override(APIClientAtom()) { _ in StubAPIClient() } } } ``` -------------------------------- ### Bind Read-Write Atom State with @WatchState Property Wrapper Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md Shows how to use the @WatchState property wrapper for read-write access to StateAtom values. Enables two-way binding with the $ prefix to create Binding objects for TextField and other interactive controls. ```swift struct UserNameAtom: StateAtom, Hashable { func defaultValue(context: Context) -> String { "Jim" } } struct UserNameInputView: View { @WatchState(UserNameAtom()) var name var body: some View { VStack { TextField("User name", text: $name) Button("Clear") { name = "" } } } } ``` -------------------------------- ### Implement Todo Filtering View Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md Creates `TodoFilters`, a SwiftUI `View` for selecting the filtering method for todos. It uses a segmented `Picker` bound to the `FilterAtom` via `@WatchState` to allow users to choose between 'All', 'Completed', and 'Uncompleted' views. ```swift struct TodoFilters: View { @WatchState(FilterAtom()) var current var body: some View { Picker("Filter", selection: $current) { ForEach(Filter.allCases, id: \.self) { filter in switch filter { case .all: Text("All") case .completed: Text("Completed") case .uncompleted: Text("Uncompleted") } } } .pickerStyle(.segmented) } } ``` -------------------------------- ### Import Atoms Package in Swift Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md Basic import statement to use the Atoms module in your Swift source code. This statement must be added to any file using the Atoms package functionality. ```swift import Atoms ``` -------------------------------- ### Context API - Subscript Read-Write Access Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md Provides read-write access to atom values through subscript notation, enabling mutating methods to be applied directly. ```swift context[CounterAtom()].increment() ``` -------------------------------- ### Add Swift Package Dependency via Package.swift Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md Configure the swiftui-atom-properties package as a dependency in your Package.swift manifest file. This approach uses Swift Package Manager to manage the package dependency and includes it as a product for your target. ```swift .package(url: "https://github.com/ra1028/swiftui-atom-properties"), ``` ```swift .target(name: "", dependencies: [ .product(name: "Atoms", package: "swiftui-atom-properties"), ]), ``` -------------------------------- ### WatchStateObject Property Wrapper with ObservableObject Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md Creates a property wrapper that monitors observable object updates and recomputes the view when changes occur. Similar to @StateObject and @ObservedObject, it supports binding to properties using the $ prefix. Works with ObservableObjectAtom-compatible atoms. ```swift class Counter: ObservableObject { @Published var count = 0 func plus(_ value: Int) { count += value } } struct CounterAtom: ObservableObjectAtom, Hashable { func object(context: Context) -> Counter { Counter() } } struct CounterView: View { @WatchStateObject(CounterObjectAtom()) var counter var body: some View { VStack { Text("Count: \(counter.count)") Stepper(value: $counter.count) {} Button("+100") { counter.plus(100) } } } } ``` -------------------------------- ### PublisherAtom for Handling Combine Publishers Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md PublisherAtom provides an AsyncPhase value for the sequence of values from a Combine Publisher. It is useful for managing single or multiple asynchronous values, like those from API calls. The output type is AsyncPhase. ```swift struct TimerAtom: PublisherAtom, Hashable { func publisher(context: Context) -> AnyPublisher { Timer.publish(every: 1, on: .main, in: .default) .autoconnect() .eraseToAnyPublisher() } } struct TimerView: View { @Watch(TimerAtom()) var timerPhase var body: some View { if let date = timerPhase.value { Text(date.formatted(date: .numeric, time: .shortened)) } } } ``` -------------------------------- ### Handle Asynchronous Task States with Suspense in SwiftUI Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md Demonstrates the `Suspense` view modifier for handling the different phases of an asynchronous task. It allows you to define content to display while the task is running (`suspending`), the content to show upon successful completion, and content to display if the task fails (`catch`). This provides a clean way to manage loading and error states for data fetching. ```swift struct NewsView: View { @Watch(LatestNewsAtom()) var newsTask: Task var body: some View { Suspense(newsTask) { Text(news.content) } suspending: { ProgressView() } catch: { Text(error.localizedDescription) } } } ``` -------------------------------- ### Implement StateAtom with Mutable Data Binding Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md Create a StateAtom to manage mutable state like a counter value. Use the @WatchState property wrapper to enable two-way binding with dollar sign syntax for updating values in UI controls. ```swift struct CounterAtom: StateAtom, Hashable { func defaultValue(context: Context) -> Int { 0 } } struct CounterView: View { @WatchState(CounterAtom()) var count var body: some View { Stepper("Count: \(count)", value: $count) } } ``` -------------------------------- ### ObservableObjectAtom for Instantiating Observable Objects Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md ObservableObjectAtom is used to instantiate an observable object. It's designed for managing mutable complex state objects. The output type is T: ObservableObject. ```swift class Contact: ObservableObject { @Published var name = "" @Published var age = 20 func haveBirthday() { age += 1 } } struct ContactAtom: ObservableObjectAtom, Hashable { func object(context: Context) -> Contact { Contact() } } struct ContactView: View { @WatchStateObject(ContactAtom()) var contact var body: some View { VStack { TextField("Enter your name", text: $contact.name) Text("Age: \(contact.age)") Button("Celebrate your birthday!") { contact.haveBirthday() } } } } ``` -------------------------------- ### Unit Test Atom with AtomTestContext and Mock Override Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md Write a unit test using AtomTestContext to override atom dependencies with mock instances. This test demonstrates hermetic testing by creating an isolated context, injecting mock responses, and verifying atom values. The @MainActor attribute ensures thread-safety when testing atoms. ```swift class FetchBookTests: XCTestCase { @MainActor func testFetch() async throws { let context = AtomTestContext() let api = MockAPIClient() // Override the atom value with the mock instance. context.override(APIClientAtom()) { _ in api } let expected = Book(title: "A book", isbn: "ISBN000–0–0000–0000–0") // Inject the expected response to the mock. api.response = expected let book = try await context.watch(FetchBookAtom(isbn: "ISBN000–0–0000–0000–0")).value XCTAssertEqual(book, expected) } } ``` -------------------------------- ### AsyncPhaseAtom for Handling Asynchronous Operations Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md AsyncPhaseAtom provides an AsyncPhase value for the result of an asynchronous throwable function. It's useful for operations like API calls. The output type is AsyncPhase. It handles throwing or non-throwing asynchronous operations. ```swift struct FetchTrendingSongsAtom: AsyncPhaseAtom, Hashable { func value(context: Context) async throws(FetchSongsError) -> [Song] { try await fetchTrendingSongs() } } struct TrendingSongsView: View { @Watch(FetchTrendingSongsAtom()) var phase var body: some View { List { switch phase { case .success(let songs): ForEach(songs, id: \.id) { song in Text(song.title) } case .failure(.noData): Text("There are no currently trending songs.") case .failure(let error): Text(error.localizedDescription) } } } } ``` -------------------------------- ### Handle Throwing Async Operations with ThrowingTaskAtom Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md Implement ThrowingTaskAtom for throwing asynchronous operations such as API calls. The atom returns Task and supports error handling through Suspense's catch closure. ```swift struct FetchMoviesAtom: ThrowingTaskAtom, Hashable { func value(context: Context) async throws -> [Movie] { try await fetchMovies() } } struct MoviesView: View { @Watch(FetchMoviesAtom()) var moviesTask var body: some View { List { Suspense(moviesTask) { movies in ForEach(movies, id: \.id) { movie in Text(movie.title) } } catch: { error in Text(error.localizedDescription) } } } } ``` -------------------------------- ### Handle Non-Throwing Async Operations with TaskAtom Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md Use TaskAtom to manage non-throwing asynchronous operations like expensive calculations. The atom returns a Task and integrates with Suspense for handling async data loading and display. ```swift struct FetchUserAtom: TaskAtom, Hashable { func value(context: Context) async -> User? { await fetchUser() } } struct UserView: View { @Watch(FetchUserAtom()) var userTask var body: some View { Suspense(userTask) { user in Text(user?.name ?? "Unknown") } } } ``` -------------------------------- ### Time Travel Debugging with @ViewContext Snapshot and Restore Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md Implement time-travel debugging by capturing a snapshot of the atom states and dependency graph using @ViewContext's snapshot() and then restoring to that captured state using restore(). This enables investigation of past application states. ```swift @ViewContext var context @State var snapshot: Snapshot? var body: some View { VStack { Button("Capture") { snapshot = context.snapshot() } Button("Restore") { if let snapshot { context.restore(snapshot) } } } } ``` -------------------------------- ### AsyncSequenceAtom for Handling Asynchronous Sequences Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md AsyncSequenceAtom provides an AsyncPhase value for elements from an AsyncSequence. It is suitable for scenarios involving multiple asynchronous values, such as web sockets. The output type is AsyncPhase. ```swift struct NotificationAtom: AsyncSequenceAtom, Hashable { let name: Notification.Name func sequence(context: Context) -> NotificationCenter.Notifications { NotificationCenter.default.notifications(named: name) } } struct NotificationView: View { @Watch(NotificationAtom(name: UIApplication.didBecomeActiveNotification)) var notificationPhase var body: some View { switch notificationPhase { case .suspending, .failure: Text("Unknown") case .success: Text("Active") } } } ``` -------------------------------- ### Observe All State Changes with AtomRoot .observe Modifier Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md Continuously receive snapshots of the dependency graph for all state changes in the application by applying the .observe modifier to AtomRoot. This allows for real-time monitoring of the entire app's atom state. ```swift AtomRoot { HomeScreen() } .observe { snapshot in print(snapshot.graphDescription()) } ``` -------------------------------- ### Bind Atom State to SwiftUI Views Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md This code demonstrates how to bind an atom's state to a SwiftUI View using the @WatchState property wrapper. The CountStepper view uses @WatchState to access and modify the count managed by CounterAtom. Changes to the count will automatically update the view, and user interactions with the Stepper will update the atom's state. ```swift struct CountStepper: View { @WatchState(CounterAtom()) var count var body: some View { Stepper(value: $count) {} } } ``` -------------------------------- ### Define Todo Entity, Filter Enum, and State Atoms Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md Defines the data structure for a todo item, an enum for filtering options, and two `StateAtom` instances: `TodosAtom` for mutable todo list state and `FilterAtom` for the current filter state. These atoms manage the application's core state. ```swift struct Todo { var id: UUID var text: String var isCompleted: Bool } enum Filter: CaseIterable, Hashable { case all, completed, uncompleted } struct TodosAtom: StateAtom, Hashable { func defaultValue(context: Context) -> [Todo] { [] } } struct FilterAtom: StateAtom, Hashable { func defaultValue(context: Context) -> Filter { .all } } ``` -------------------------------- ### Atom Effect for State Persistence in SwiftUI Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md Shows how to implement an UpdateEffect for an atom to persist its state using UserDefaults. This effect runs whenever the atom's value is updated, synchronizing it with persistent storage. ```swift struct CounterAtom: StateAtom, Hashable { func defaultValue(context: Context) -> Int { UserDefaults.standard.integer(forKey: "persistence_key") } func effect(context: CurrentContext) -> some AtomEffect { UpdateEffect { UserDefaults.standard.set(context.read(self), forKey: "persistence_key") } } } ``` -------------------------------- ### ViewContext Property Wrapper for Functional Atom Control Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md Provides an AtomViewContext to views for functional control of atoms beyond single-atom binding. Enables operations like refresh() to reset asynchronous atom values and reset() to clear current values. Supports dynamic parameter passing to atom initializers. ```swift struct FetchBookAtom: ThrowingTaskAtom, Hashable { let id: Int func value(context: Context) async throws -> Book { try await fetchBook(id: id) } } struct BookView: View { @ViewContext var context let id: Int var body: some View { let task = context.watch(FetchBookAtom(id: id)) Suspense(task) { book in Text(book.content) } suspending: { ProgressView() } } } ``` -------------------------------- ### Bind Read-Only Atom Value with @Watch Property Wrapper Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md Illustrates using the @Watch property wrapper to create a read-only binding to an atom value. The view automatically recomputes when the watched atom value changes, similar to @State or @Environment. ```swift struct UserNameAtom: StateAtom, Hashable { func defaultValue(context: Context) -> String { "John" } } struct UserNameDisplayView: View { @Watch(UserNameAtom()) var name var body: some View { Text("User name: \(name)") } } ``` -------------------------------- ### Create Derived Value Atom for Filtered Todos Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md Implements `FilteredTodosAtom`, a `ValueAtom` that derives a filtered list of todos based on the current filter state. It watches `FilterAtom` and `TodosAtom` and reactively updates when their values change, caching the result for performance. ```swift struct FilteredTodosAtom: ValueAtom, Hashable { func value(context: Context) -> [Todo] { let filter = context.watch(FilterAtom()) let todos = context.watch(TodosAtom()) switch filter { case .all: return todos case .completed: return todos.filter(\.isCompleted) case .uncompleted: return todos.filter { !$0.isCompleted } } } } ``` -------------------------------- ### Use Atoms Inside Objects with AtomContext Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md This code illustrates how to use atoms within an `ObservableObject` to manage asynchronous data loading. The `MessageLoaderAtom` creates a `MessageLoader` instance, which holds an `AtomContext`. This context allows the `MessageLoader` to interact with other atoms, such as `APIClientAtom`, to fetch data. It also demonstrates preventing re-creation of the object by passing the context explicitly as `AtomContext` type when calling `watch` or `read`. ```swift struct MessageLoaderAtom: ObservableObjectAtom, Hashable { func object(context: Context) -> MessageLoader { MessageLoader(context: context) } } @MainActor class MessageLoader: ObservableObject { let context: AtomContext @Published var phase = AsyncPhase<[Message], any Error>.suspending init(context: AtomContext) { self.context = context } func load() async { let api = context.read(APIClientAtom()) phase = await AsyncPhase { try await api.fetchMessages(offset: 0) } } func loadNext() async { guard let messages = phase.value else { return } let api = context.read(APIClientAtom()) let nextPhase = await AsyncPhase { try await api.fetchMessages(offset: messages.count) } phase = nextPhase.map { messages + $0 } } } ``` -------------------------------- ### Use ValueAtom for Read-Only Computed Values Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md Implement a ValueAtom to provide read-only derived data like locale information. Use the @Watch property wrapper in views to access the atom's value with automatic data-binding and reactivity. ```swift struct LocaleAtom: ValueAtom, Hashable { func value(context: Context) -> Locale { .current } } struct LocaleView: View { @Watch(LocaleAtom()) var locale var body: some View { Text(locale.identifier) } } ``` -------------------------------- ### Context API - Set New Atom Value Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md Sets a new value to an atom, replacing its current cached value. ```swift context.set(newValue, for: CounterAtom()) ``` -------------------------------- ### Derive Changes of Specific Property in SwiftUI Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md Derives a partial property from an atom using a key path and prevents downstream updates if the new value is equivalent to the old one. Requires the derived property to be Equatable. ```swift struct CountAtom: StateAtom, Hashable { func defaultValue(context: Context) -> Int { 12345 } } struct CountDisplayView: View { @Watch(CountAtom().changes(of: \.description)) var description // : String var body: some View { Text(description) } } ``` -------------------------------- ### Scope Atom Updates and Observe Changes in SwiftUI Views Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md Illustrates how to use `AtomScope` to manage atom states within a specific part of the view hierarchy. It allows for observing atom updates using `scopedObserve` and overriding atom values within the scope. This is useful for localizing atom state management and debugging. ```swift AtomScope { CounterView() } .scopedObserve { snapshot in if let count = snapshot.lookup(CounterAtom()) { print(count) } } ``` -------------------------------- ### Implement Scoped Attribute for Isolated Atom State Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md Shows how to use the Scoped attribute to preserve atom state within individual AtomScope boundaries, preventing state sharing across different scopes. Each SearchPane instance maintains its own isolated SearchQueryAtom state. ```swift struct SearchQueryAtom: StateAtom, Scoped, Hashable { func defaultValue(context: Context) -> String { "" } } VStack { AtomScope { SearchPane() } AtomScope { SearchPane() } } ``` -------------------------------- ### Implement KeepAlive Attribute for Data Preservation Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md Demonstrates using the KeepAlive attribute to preserve atom data in memory even when not actively watched. Combined with Scoped, the atom persists until the AtomScope is removed from the view hierarchy, ideal for caching server-fetched master data. ```swift struct FetchMasterDataAtom: ThrowingTaskAtom, KeepAlive, Hashable { func value(context: Context) async throws -> MasterData { try await fetchMasterData() } } ``` -------------------------------- ### Explicitly Propagate Atom Store with AtomDerivedScope in SwiftUI Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md Shows the usage of `AtomDerivedScope` to explicitly propagate an atom store through the view hierarchy when it might not be automatically inherited. This is achieved by providing a `ViewContext` to `AtomDerivedScope`, ensuring that descendant views can access and interact with atoms. ```swift struct MailView: View { @ViewContext var context var body: some View { AtomDerivedScope(context) { WrappedMailView() } } } ``` -------------------------------- ### Context API - Reset Atom to Default Value Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md Clears the current atom value, resetting it to the default value or first output. Useful for clearing cached state. ```swift context.reset(CounterAtom()) ``` -------------------------------- ### Context API - Refresh Asynchronous Atom Value Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md Resets an asynchronous atom value and waits for the completion of the new operation. Useful for refreshing remote data or async computations. ```swift await context.refresh(FetchMoviesAtom()) ``` -------------------------------- ### Override Atom Value in AtomRoot Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md Override an atom's value at the AtomRoot level to return a custom value throughout all descendant views. This is useful for dependency injection or faking state during testing. The override applies globally to all instances of the specified atom within the AtomRoot scope. ```swift AtomRoot { RootView() } .override(CounterAtom()) { _ in 456 } ``` -------------------------------- ### Read Atom Value Without Watching Updates Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md Retrieve the current value of an atom without subscribing to its future updates using the context.read() function. This is typically used in event handlers or functions that only need a snapshot of the data at a specific moment. ```swift struct TextAtom: StateAtom, Hashable { func value(context: Context) -> String { "" } } struct TextCopyView: View { @ViewContext var context var body: some View { Button("Copy") { UIPasteboard.general.string = context.read(TextAtom()) } } } ``` -------------------------------- ### Animate Atom Value Changes in SwiftUI Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md Applies animation to a view when the watched atom's value updates. This modifier is compatible with all atom types and enhances the user experience by visually indicating state changes. ```swift struct TextAtom: ValueAtom, Hashable { func value(context: Context) -> String { "" } } struct ExampleView: View { @Watch(TextAtom().animation()) var text var body: some View { Text(text) } } ``` -------------------------------- ### Scoped Atom with Scope ID in SwiftUI Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md Illustrates using a custom scope ID with Scoped atoms and AtomScope to target a specific scope for state management. This allows nested scopes to share state within a designated scope. ```swift struct TextScopeID: Hashable {} struct TextInputAtom: StateAtom, Scoped, Hashable { var scopeID: TextScopeID { TextScopeID() } func defaultValue(context: Context) -> String { "" } } AtomScope(id: TextScopeID()) { TextInputView() AtomScope { // Shares TextInputAtom state with the TextInputView placed in the parent scope. TextInputView() } } ``` -------------------------------- ### Context API - Modify Cached Atom Value Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md Modifies the cached atom value using a closure, allowing incremental updates to the atom state. ```swift context.modify(CounterAtom()) { value in value += 1 } ``` -------------------------------- ### Prevent Updates on Same Value in SwiftUI Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md Prevents an atom from updating its child views or atoms when its new value is the same as the old value. This is useful for performance optimization and requires the atom's value to be Equatable. ```swift struct CountAtom: StateAtom, Hashable { func defaultValue(context: Context) -> Int { 12345 } } struct CountDisplayView: View { @Watch(CountAtom().changes) var count // : Int var body: some View { Text(count.description) } } ``` -------------------------------- ### Scoped Override Atom Value in AtomScope Source: https://github.com/ra1028/swiftui-atom-properties/blob/main/README.md Override an atom's value within a specific AtomScope, limiting the override to only that scope and its descendants. Other nested AtomScopes will not inherit this override. This provides more granular control over atom state overrides compared to AtomRoot. ```swift AtomScope { CountDisplay() // CounterAtom is not overridden in this scope. AtomScope { CountDisplay() } } .scopedOverride(CounterAtom()) { _ in 456 } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.