본문 바로가기
Swift

SwiftUI와 Combine을 활용한 TCA 아키텍처 TodoList 예제

by mr.conan 2023. 7. 11.
728x90
반응형

안녕하세요! 이번에는 SwiftUI와 Combine을 사용하여 TCA(Typed Redux with Combine) 아키텍처를 활용한 TodoList 예제를 소개하겠습니다. TCA는 SwiftUI와 Combine을 결합하여 상태 관리와 애플리케이션 로직을 효과적으로 관리할 수 있는 아키텍처 패턴입니다.

 

 

상태(State) 정의하기 TodoList의 상태를 정의하기 위해 구조체로서의 상태(State)를 만듭니다. 아래와 같이 코드를 작성해주세요.

struct TodoState: Equatable {
    var todos: [Todo] = []
}

struct Todo: Equatable, Identifiable {
    var id: UUID = UUID()
    var title: String
    var isCompleted: Bool = false
}

 

 

액션(Action) 정의하기 TodoList에서 사용자 동작을 나타내는 액션(Action)을 정의합니다. 예를 들어, 할 일 추가, 할 일 완료, 할 일 삭제 등의 액션을 정의할 수 있습니다. 아래는 일부 예시입니다.

enum TodoAction: Equatable {
    case addTodo
    case removeTodos(IndexSet)
    case toggleComplete(index: Int)
    // 추가적인 액션들을 여기에 추가해주세요.
}

 

 

반응형

 

리듀서(Reducer) 정의하기 리듀서는 현재 상태와 액션을 입력으로 받아 새로운 상태를 반환하는 함수입니다. 아래와 같이 리듀서를 정의해줍니다.

let todoReducer = Reducer<TodoState, TodoAction, Void> { state, action, _ in
    switch action {
    case .addTodo:
        state.todos.append(Todo(title: ""))
    case let .removeTodos(indices):
        state.todos.remove(atOffsets: indices)
    case let .toggleComplete(index):
        state.todos[index].isCompleted.toggle()
    }
    return .none
}

 

 

뷰(View) 정의하기 마지막으로 SwiftUI를 사용하여 TodoList 인터페이스를 구성하는 뷰를 정의합니다. 뷰에서는 상태와 액션을 연결하여 사용자 입력을 처리하고, 상태를 업데이트합니다. 예시 코드는 아래와 같습니다.

struct TodoListView: View {
    let store: Store<TodoState, TodoAction>
    
    var body: some View {
        WithViewStore(store) { viewStore in
            VStack {
                List {
                    ForEach(viewStore.todos) { todo in
                        HStack {
                            Image(systemName: todo.isCompleted ? "checkmark.circle.fill" : "circle")
                                .foregroundColor(.blue)
                                .onTapGesture {
                                    viewStore.send(.toggleComplete(index: viewStore.todos.firstIndex(of: todo)!))
                                }
                            
                            TextField("할 일", text: viewStore.binding(
                                get: { $0.todos[viewStore.todos.firstIndex(of: todo)!].title },
                                send: { .none }
                            ))
                        }
                    }
                    .onDelete { indices in
                        viewStore.send(.removeTodos(indices))
                    }
                }
                
                Button(action: {
                    viewStore.send(.addTodo)
                }) {
                    Text("할 일 추가")
                        .font(.headline)
                        .padding()
                        .background(Color.green)
                        .foregroundColor(.white)
                        .cornerRadius(10)
                }
            }
            .padding()
        }
    }
}

 

 

 

뷰 연결하기 마지막으로, 앞에서 정의한 뷰와 리듀서를 연결하여 최종적인 앱을 구성합니다. 아래와 같이 코드를 작성해주세요.

@main
struct TodoListApp: App {
    var body: some Scene {
        WindowGroup {
            let store = Store(initialState: TodoState(),
                              reducer: todoReducer,
                              environment: ())
            
            TodoListView(store: store)
        }
    }
}

 

 

이제 SwiftUI와 Combine을 활용하여 TCA 아키텍처를 사용한 TodoList 앱을 만들었습니다. 할 일을 추가하고 완료 표시를 하며, 삭제도 가능합니다. 추가적인 기능을 구현하거나 UI를 확장하는 등 원하는 대로 코드를 수정해보세요. TodoList 예제를 통해 TCA 아키텍처의 간결함과 확장성을 경험해보시기 바랍니다.

728x90
반응형