티스토리 뷰

CoreData는 실행 취소와 다시 실행을 지원한다.

이와 관련된 메서드는 NSManagedObjectContext에 포함되어 있다.

 

컨텍스트란?

NSManagedObjectContext는 CoreData의 컨텍스트를 의미한다.

컨텍스트는 실제 저장소의 데이터가 아닌 저장소의 데이터를 불러와(fetch) 임시로 메모리에 올려서 사용하는 장소라고 생각하면된다.

따라서 컨텍스트에 데이터를 추가하거나 저장소에서 불러온 데이터를 수정하고 삭제하여도 실제 저장소에 영향을 주지 않는다.

save()를 호출해야 컨텍스트의 내용이 실제 저장소에 반영된다.

 

실행 취소와 다시 실행 관련 메서드

컨텍스트에는 실행 취소와 다시 실행과 관련하여 다음 메서드를 제공한다.

undo() : 실행을 취소한다. (save도 취소할 수 있다.)

redo() : undo()로 실행 취소를 한 것을 되돌린다.

rollback() : 마지막 저장 시점으로 되돌리고, UndoManager의 실행 스택을 초기화한다.

save() : 컨텍스트를 저장한다.

 

reset() 메서드도 제공하는데, 이 메서드는 컨텍스트 자체를 제공하기 때문에 SwiftUI에서는 사용할 일이 없는 것 같다. 처음에 rollback과 reset의 차이점을 알지 못해서 적어둔다.

 

설정 작업

실행 취소와 다시 실행를 사용하기 위해서 컨텍스트의 undoManager는 기본적으로 nil로 되어 있다. 그래서 UndoManager 인스턴스를 설정해줘야 한다.

 

실행 스택이란?

UndoManager는 실행 스택을 가진다. 

처음에는 실행 스택에 아무 내용도 포함되어 있지 않다.

컨텍스트에 데이터를 추가하거나 수정하거나 저장하는 모든 실행이 실행 스택에 순서대로 추가된다.

 

실행 스택은 스택처럼 작동하기 때문에 실행 취소 시 마지막 실행이 취소된다. 

또한 다시 실행 역시 스택처럼 작동하기 때문에 취소한 마지막 실행이 다시 실행된다.

 

실행 스택은 rollback()이 실행되기 전까지는 모든 실행 스택이 포함된다. 

따라서 save()를 한 내용도 실행 취소할 수 있다. 

 

하지만 rollback()이 실행되면 마지막 save()가 실행된 시점으로 되돌아가고, 실행 스택도 초기화가 된다.

 

 

실습 예제

import SwiftUI
import CoreData

struct ContentView: View {
    @Environment(\.managedObjectContext) private var viewContext
    private var undoManager = UndoManager()
    
    @FetchRequest(
        sortDescriptors: [NSSortDescriptor(keyPath: \Item.name, ascending: true)],
        animation: .default)
    private var items: FetchedResults<Item>
    
    var body: some View {
        VStack {
            Form {
                Button(action: {
                    let item = Item(context: viewContext)
                    item.name = "New"
                    viewContext.insert(item)
                }, label: {
                    Text("Create New Item")
                })
                
                Button(action: {
                    viewContext.undo()
                }, label: {
                    Text("undo")
                })
                .disabled(!undoManager.canUndo)
                
                Button(action: {
                    viewContext.redo()
                }, label: {
                    Text("redo")
                })
                .disabled(!undoManager.canRedo)
                
                Button(action: {
                    viewContext.rollback()
                }, label: {
                    Text("rollback")
                })
                
                Button(action: {
                    try! viewContext.save()
                }, label: {
                    Text("save")
                })
                
                Section {
                    List(items) { item in
                        Text(item.name!)
                    }
                    .onAppear {
                        viewContext.undoManager = undoManager
                    }
                }
            }
        }
    }
}

'CoreData' 카테고리의 다른 글

[CoreData] 인스턴스 변수로 predicate 설정하는 방법  (0) 2023.08.23
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/06   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30
글 보관함