A library that provides undo semantics for the Composable Architecture with optional bridging tofUndoManager.

Overview

Swift Composable Undo

A library that provides undo semantics for the Composable Architecture with optional bridging with UndoManager.

Motivation

It is hard to use UndoManager API with state that uses value sematics. Furthermore, the instance provided by SwiftUI may not be available in all contexts. There have been previous discussions which resulted in solutions that were not generic. This library provides a way to scope Undo/Redo operations within a View with minimal efforts.

Example

The workspace ComposableUndo contains the TicTacToe demo from ComposableArchitecture repository. Open the GameCore.swift file to see how Composable Undo is integrated.

Basic Usage

To use ComposableUndo in your project, you need to annotate the state fields that needs undo tracking:

struct Person: Equatable {
  var firstName: String
  var lastName: String
  var phoneNumber: String
}

struct AppState: Equatable {
  @CheckpointState var person: Person
}

You also need to add checkpoint action to your domain. It is advisable to confirm the domain action enum to SingleCheckpointAction protocol when only one of the states fields is annotated:

enum AppAction: Equatable, SingleCheckpointAction {
  case checkpoint(CheckpointAction)
  // Your domain's other actions:
  ...
}

If you are planning to use UndoManager, it must be registered using view lifecycle methods:

struct AppView: View {
  @Environment(\.undoManager) var undoManager
  // Store declarations
  ...
  
  var body: some View {
    WithViewStore(store) { viewStore in
      SomeView {
        ...
      }
      .onAppear { viewStore.send(.checkpoint(.attachManager(undoManager))) }
      .onDisappear { viewStore.send(.checkpoint(.detachManager)) }
    }
  }
}

If this view's state is computed by a super view, make sure that the detach happens before clearing the state. See NewGameCore.swift in the example on how to do this.

With this initial setup out of the way, each state change that can be undone must be registered by returning effect from the reducer:

case .updatePerson:
 // ... code to update state
 return .checkpoint(.register("Change person"))

Note that the register string is passed on to UndoManager and appears in the menu on macOS.

You might also like...
The app provides additional actions for the Shortcuts app on macOS and iOS.
The app provides additional actions for the Shortcuts app on macOS and iOS.

Actions Supercharge your shortcuts The app provides additional actions for the Shortcuts app on macOS and iOS. Submit action idea (Submit an issue bef

A mobile application project designed for everybody which provides the easiest way to make searchs for public services
A mobile application project designed for everybody which provides the easiest way to make searchs for public services

A mobile application project designed for everybody which provides the easiest way to make searchs for public services

A simple and lightweight Swift package which provides a SwiftUI view for interactive geo coordinates input!
A simple and lightweight Swift package which provides a SwiftUI view for interactive geo coordinates input!

LocationPicker for SwiftUI LocationPicker for SwiftUI is a very simple and lightweight Swift package which provides you a SwiftUI view for interactive

🖼 Gallery App for Harvest (Elm Architecture + Optics) + SwiftUI + Combine.
🖼 Gallery App for Harvest (Elm Architecture + Optics) + SwiftUI + Combine.

🖼 Harvest-SwiftUI-Gallery Gallery App for Harvest (Elm Architecture + Optics) + SwiftUI + Combine. Examples Todo List Stopwatch GitHub Search TimeTra

SwiftUI sample app using Clean Architecture. Examples of working with CoreData persistence, networking, dependency injection, unit testing, and more.
SwiftUI sample app using Clean Architecture. Examples of working with CoreData persistence, networking, dependency injection, unit testing, and more.

Articles related to this project Clean Architecture for SwiftUI Programmatic navigation in SwiftUI project Separation of Concerns in Software Design C

Porting the example app from our Advanced iOS App Architecture book from UIKit to SwiftUI.

SwiftUI example app: Koober We're porting the example app from our Advanced iOS App Architecture book from UIKit to SwiftUI and we are sharing the cod

An iOS template project using SwiftUI, Combine and MVVM-C software architecture
An iOS template project using SwiftUI, Combine and MVVM-C software architecture

SwiftUI-MVVM-C A template project that uses SwiftUI for UI, Combine for event handling, MVVM-C for software architecture. I have done some small proje

Comments
  • Tic-Tac-Toe example: Capture currentPlayer.label before toggling currentPlayer

    Tic-Tac-Toe example: Capture currentPlayer.label before toggling currentPlayer

    Hey @surajbarkale

    Not sure if I'm understanding this correctly, but should you do something like

    let checkpointLabel = "\(state.currentPlayer.label)'s move"
    

    before calling state.currentPlayer.toggle() so .checkpoint(.register(checkpointLabel)) uses the player that just had their turn?

    https://github.com/aacapella/swift-composable-undo/blob/66b447b84365df3a1c7e5e75598d6167592c4af1/Example/tic-tac-toe/Sources/GameCore/GameCore.swift#L79-L90

    opened by iampatbrown 1
Releases(v0.1.0)
Owner
Aacapella Holdings Pty. Ltd.
Aacapella Holdings Pty. Ltd.
A library to derive and compose Environment's in The Composable Architecture.

ComposableEnvironment This library brings an API similar to SwiftUI's Environment to derive and compose Environment's in The Composable Architecture.

Thomas Grapperon 129 Dec 14, 2022
Learn how to structure your iOS App with declarative state changes using Point-Free's The Composable Architecture (TCA) library.

Learn how to structure your iOS App with declarative state changes using Point-Free's The Composable Architecture (TCA) library.

Tiago Henriques 0 Oct 2, 2022
Open source game built in SwiftUI and the Composable Architecture.

isowords This repo contains the full source code for isowords, an iOS word search game played on a vanishing cube. Connect touching letters to form wo

Point-Free 2.1k Jan 1, 2023
Pointfree's Composable Architecture Relay

RelayStore Pointfree's Composable Architecture Relay to hook into Actions sent to the Store from outside. Read more at Observe actions in The Composab

Alejandro Martínez 3 May 29, 2022
ScrumdingerTCA - Apple’s tutorial app recreated using The Composable Architecture

ScrumdingerTCA Apple’s tutorial app recreated using The Composable Architecture

Pat Brown 9 Nov 29, 2022
Best architecture for SwiftUI + CombineBest architecture for SwiftUI + Combine

Best architecture for SwiftUI + Combine The content of the presentation: First of the proposed architectures - MVP + C Second of the proposed architec

Kyrylo Triskalo 3 Sep 1, 2022
Mvi Architecture for SwiftUI Apps. MVI is a unidirectional data flow architecture.

Mvi-SwiftUI If you like to read this on Medium , you can find it here MVI Architecture for SwiftUI Apps MVI Architecture Model-View-Intent (MVI) is a

null 12 Dec 7, 2022
Deck is a library that provides a UI to reproduce stacked cards for SwiftUI.

Deck Deck is a library that provides a UI to reproduce stacked cards for SwiftUI. RPReplay_Final1624531727.mov Usage struct Card: View { var data

1amageek 21 Dec 14, 2022
A cooking book provides recipes to perform certain action on SwiftUI

SwiftUI Recipes This is like a cooking book. provides recipes to perform certain action on SwiftUI Every Project will contain as many SwiftUI views as

Julio Ismael Robles 2 Nov 23, 2021