I have a sample macOS app that I'm working on. I can run the exactly same lines of code below for iOS. For now, I'm running code for macOS since I can just press Command + z to undo the last action.
Anyway, I have two Text View objects. Since TextView has the DragGesture gesture, I am able to freely move either of them. And I want to undo and redo their positions. So the following is what I have.
import SwiftUI
struct ContentView: View {
@State var textViews: [TextView] = [TextView(text: "George"), TextView(text: "Susan")]
var body: some View {
VStack {
ForEach(textViews, id: \.id) { textView in
textView
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
struct TextView: View {
@Environment(\.undoManager) var undoManager
@StateObject private var undoModel = UndoViewModel()
@State private var dragOffset: CGSize = .zero
@State private var position: CGSize = .zero
let id = UUID()
let text: String
init(text: String) {
self.text = text
}
var body: some View {
ZStack {
Text(text)
.fixedSize()
.padding(.vertical, 10)
.offset(x: dragOffset.width + position.width, y: dragOffset.height + position.height)
.gesture(
DragGesture()
.onChanged {
self.dragOffset = $0.translation
}
.onEnded( { (value) in
self.position.width += value.translation.width
self.position.height += value.translation.height
self.dragOffset = .zero
undoModel.registerUndo(CGSize(width: position.width, height: position.height), in: undoManager)
})
)
}
}
}
class UndoViewModel: ObservableObject {
@Published var point = CGSize.zero
func registerUndo(_ newValue: CGSize, in undoManager: UndoManager?) {
let oldValue = point
undoManager?.registerUndo(withTarget: self) { [weak undoManager] target in
target.point = oldValue // registers an undo operation to revert to old text
target.registerUndo(oldValue, in: undoManager) // this makes redo possible
}
undoManager?.setActionName("Move")
point = newValue // update the actual value
}
}
Well, if I press Command + z after moving one of them, it won't return to the last position. What am I doing wrong? Muchos thankos.