Skip to content

Commit 1b4698c

Browse files
committed
refactor: reduce 메서드 분리 및 얼럿 로직 추가
1 parent 4dadf3d commit 1b4698c

1 file changed

Lines changed: 105 additions & 53 deletions

File tree

DevLog/Presentation/ViewModel/HomeViewModel.swift

Lines changed: 105 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -9,45 +9,35 @@ import Foundation
99

1010
final class HomeViewModel: Store {
1111
struct State {
12-
// UI
1312
var todoKindPreferences = TodoKind.allCases.map { TodoKindPreference(kind: $0, isVisible: true) }
1413
var pinnedTodos: [Todo] = []
1514
var showTodoKindPicker: Bool = false
1615
var showTodoEditor: Bool = false
1716
var showSearchView: Bool = false
1817
var selectedTodoKind: TodoKind?
19-
20-
// User Input
2118
var searchText: String = ""
2219
var isSearching: Bool = false
2320
var reorderTodo: Bool = false
24-
25-
// Side Effect UI
2621
var isLoading: Bool = false
27-
var toastMessage: String = ""
28-
var showToast: Bool = false
22+
var showAlert: Bool = false
23+
var alertTitle: String = ""
24+
var alertMessage: String = ""
2925
}
3026

3127
enum Action {
32-
// Life Cycle
33-
case onAppear
34-
35-
// User
3628
case tapTodoKind(TodoKind)
37-
case upsertTodo(Todo)
3829
case orderTodoKindPreferences([TodoKindPreference])
39-
40-
// Binding
41-
case updateSearching(Bool)
42-
case updateSearchText(String)
4330
case setReorderTodo(Bool)
4431
case setShowTodoEditor(Bool)
4532
case setShowTodoKindPicker(Bool)
4633
case setShowSearchView(Bool)
47-
case setShowToast(Bool)
48-
49-
// Call from run
50-
case didFetchPinnedTodos([Todo])
34+
case setAlert(Bool)
35+
case onAppear
36+
case updateSearching(Bool)
37+
case updateSearchText(String)
38+
case upsertTodo(Todo)
39+
case fetchPinnedTodos([Todo])
40+
case setLoading(Bool)
5141
}
5242

5343
enum SideEffect {
@@ -69,53 +59,115 @@ final class HomeViewModel: Store {
6959

7060
func reduce(with action: Action) -> [SideEffect] {
7161
var state = self.state
62+
var effects: [SideEffect] = []
63+
7264
switch action {
73-
case .onAppear:
74-
return [.fetchPinnedTodos]
75-
case .tapTodoKind(let kind):
76-
state.selectedTodoKind = kind
77-
state.showTodoKindPicker = false
78-
state.showTodoEditor = true
79-
case .updateSearching(let value):
80-
state.isSearching = value
81-
case .updateSearchText(let value):
82-
state.searchText = value
83-
case .setReorderTodo(let value):
84-
state.reorderTodo = value
85-
case .setShowTodoEditor(let value):
86-
state.showTodoEditor = value
87-
if !value {
88-
state.selectedTodoKind = nil
89-
}
90-
case .setShowTodoKindPicker(let value):
91-
state.showTodoKindPicker = value
92-
case .setShowSearchView(let value):
93-
state.showSearchView = value
94-
case .setShowToast(let value):
95-
state.showToast = value
96-
case .upsertTodo(let value):
97-
return [.upsertTodo(value)]
98-
case .orderTodoKindPreferences(let value):
99-
state.todoKindPreferences = value
100-
case .didFetchPinnedTodos(let todos):
101-
state.pinnedTodos = todos
65+
case .tapTodoKind, .orderTodoKindPreferences, .setReorderTodo,
66+
.setShowTodoEditor, .setShowTodoKindPicker, .setShowSearchView, .setAlert:
67+
effects = reduceByUser(action, state: &state)
68+
69+
case .onAppear, .updateSearching, .updateSearchText, .upsertTodo:
70+
effects = reduceByView(action, state: &state)
71+
72+
case .fetchPinnedTodos, .setLoading:
73+
effects = reduceByRun(action, state: &state)
10274
}
10375

10476
self.state = state
105-
return []
77+
return effects
10678
}
10779

10880
func run(_ effect: SideEffect) {
10981
switch effect {
11082
case .upsertTodo(let todo):
11183
Task {
112-
try await upsertTodoUseCase.execute(todo)
84+
do {
85+
defer { send(.setLoading(false)) }
86+
send(.setLoading(true))
87+
try await upsertTodoUseCase.execute(todo)
88+
} catch {
89+
send(.setAlert(true))
90+
}
11391
}
11492
case .fetchPinnedTodos:
11593
Task {
116-
let todos = try await fetchPinnedTodosUseCase.execute()
117-
send(.didFetchPinnedTodos(todos))
94+
do {
95+
defer { send(.setLoading(false)) }
96+
send(.setLoading(true))
97+
let todos = try await fetchPinnedTodosUseCase.execute()
98+
send(.fetchPinnedTodos(todos))
99+
} catch {
100+
send(.setAlert(true))
101+
}
118102
}
119103
}
120104
}
121105
}
106+
107+
// MARK: - Reduce Methods
108+
private extension HomeViewModel {
109+
func reduceByUser(_ action: Action, state: inout State) -> [SideEffect] {
110+
switch action {
111+
case .tapTodoKind(let kind):
112+
state.selectedTodoKind = kind
113+
state.showTodoKindPicker = false
114+
state.showTodoEditor = true
115+
case .orderTodoKindPreferences(let preferences):
116+
state.todoKindPreferences = preferences
117+
case .setReorderTodo(let isPresented):
118+
state.reorderTodo = isPresented
119+
case .setShowTodoEditor(let isPresented):
120+
state.showTodoEditor = isPresented
121+
if !isPresented { state.selectedTodoKind = nil }
122+
case .setShowTodoKindPicker(let isPresented):
123+
state.showTodoKindPicker = isPresented
124+
case .setShowSearchView(let isPresented):
125+
state.showSearchView = isPresented
126+
case .setAlert(let isPresented):
127+
setAlert(&state, isPresented: isPresented)
128+
default:
129+
break
130+
}
131+
return []
132+
}
133+
134+
func reduceByView(_ action: Action, state: inout State) -> [SideEffect] {
135+
switch action {
136+
case .onAppear:
137+
return [.fetchPinnedTodos]
138+
case .updateSearching(let isSearching):
139+
state.isSearching = isSearching
140+
case .updateSearchText(let text):
141+
state.searchText = text
142+
case .upsertTodo(let todo):
143+
return [.upsertTodo(todo)]
144+
default:
145+
break
146+
}
147+
return []
148+
}
149+
150+
func reduceByRun(_ action: Action, state: inout State) -> [SideEffect] {
151+
switch action {
152+
case .fetchPinnedTodos(let todos):
153+
state.pinnedTodos = todos
154+
case .setLoading(let isLoading):
155+
state.isLoading = isLoading
156+
default:
157+
break
158+
}
159+
return []
160+
}
161+
}
162+
163+
// MARK: - Helper Methods
164+
private extension HomeViewModel {
165+
func setAlert(
166+
_ state: inout State,
167+
isPresented: Bool
168+
) {
169+
state.alertTitle = "오류"
170+
state.alertMessage = "문제가 발생했습니다. 잠시 후 다시 시도해주세요."
171+
state.showAlert = isPresented
172+
}
173+
}

0 commit comments

Comments
 (0)