Skip to content

Commit 65a49d1

Browse files
committed
refactor: 캐시 제거 후 딕셔너리로 데이터르 변환해 날짜 조회 시 성능 개선
1 parent c087c2b commit 65a49d1

1 file changed

Lines changed: 58 additions & 29 deletions

File tree

DevLog/Presentation/ViewModel/ProfileViewModel.swift

Lines changed: 58 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ final class ProfileViewModel: Store {
1414
var statusMessage: String = ""
1515
var avatarURL: URL?
1616
var selectedQuarterStart: Date?
17-
var completionQuarterCache: [Date: ProfileCompletionQuarter] = [:]
18-
var quarterTodosCache: [Date: [Todo]] = [:]
17+
var completionQuarter: ProfileCompletionQuarter?
18+
var dayActivitiesByDate: [Date: [ProfileSelectedDayActivity]] = [:]
1919
var selectedActivityTypes: Set<ProfileActivityType> = [.created, .completed]
2020
var selectedDay: ProfileCompletionDay?
2121
var selectedActivityForSheet: ProfileSelectedDayActivity?
@@ -31,7 +31,11 @@ final class ProfileViewModel: Store {
3131
case tapResetStatusMessageButton
3232
case willUpdateStatusMessage
3333
case fetchUserData(UserProfile)
34-
case setCompletionQuarter(ProfileCompletionQuarter, [Todo])
34+
case setCompletionQuarter(
35+
quarterStart: Date,
36+
quarter: ProfileCompletionQuarter,
37+
dayActivitiesByDate: [Date: [ProfileSelectedDayActivity]]
38+
)
3539
case moveQuarter(Int)
3640
case toggleActivityType(ProfileActivityType)
3741
case selectDay(ProfileCompletionDay?)
@@ -68,28 +72,17 @@ final class ProfileViewModel: Store {
6872
}
6973

7074
var selectedQuarter: ProfileCompletionQuarter? {
71-
guard let selectedQuarterStart = state.selectedQuarterStart else { return nil }
72-
return state.completionQuarterCache[selectedQuarterStart]
75+
state.completionQuarter
7376
}
7477

7578
var selectedDayActivities: [ProfileSelectedDayActivity] {
76-
guard let selectedDay = state.selectedDay,
77-
let selectedQuarterStart = state.selectedQuarterStart,
78-
let todos = state.quarterTodosCache[selectedQuarterStart] else { return [] }
79+
guard let selectedDay = state.selectedDay else { return [] }
7980
let dayStart = calendar.startOfDay(for: selectedDay.date)
81+
let activities = state.dayActivitiesByDate[dayStart] ?? []
8082

81-
return todos.compactMap { todo in
82-
let isCreated = state.selectedActivityTypes.contains(.created)
83-
&& calendar.startOfDay(for: todo.createdAt) == dayStart
84-
let isCompleted = state.selectedActivityTypes.contains(.completed)
85-
&& todo.isCompleted
86-
&& calendar.startOfDay(for: todo.updatedAt) == dayStart
87-
guard isCreated || isCompleted else { return nil }
88-
return ProfileSelectedDayActivity(
89-
todo: todo,
90-
showsCreated: isCreated,
91-
showsCompleted: isCompleted
92-
)
83+
return activities.filter { activity in
84+
(state.selectedActivityTypes.contains(.created) && activity.showsCreated)
85+
|| (state.selectedActivityTypes.contains(.completed) && activity.showsCompleted)
9386
}
9487
}
9588

@@ -130,8 +123,7 @@ final class ProfileViewModel: Store {
130123
state.selectedActivityTypes = settings
131124
}
132125
effects = [.fetchUserData]
133-
if let selectedQuarterStart = state.selectedQuarterStart,
134-
state.completionQuarterCache[selectedQuarterStart] == nil {
126+
if let selectedQuarterStart = state.selectedQuarterStart {
135127
effects.append(.fetchCompletionQuarter(selectedQuarterStart))
136128
}
137129
case .setAlert(let isPresented):
@@ -143,9 +135,10 @@ final class ProfileViewModel: Store {
143135
state.email = profile.email
144136
state.statusMessage = profile.statusMessage
145137
state.avatarURL = profile.avatarURL
146-
case .setCompletionQuarter(let quarter, let todos):
147-
state.completionQuarterCache[quarter.quarterStart] = quarter
148-
state.quarterTodosCache[quarter.quarterStart] = todos
138+
case .setCompletionQuarter(let quarterStart, let quarter, let dayActivitiesByDate):
139+
guard state.selectedQuarterStart == quarterStart else { break }
140+
state.completionQuarter = quarter
141+
state.dayActivitiesByDate = dayActivitiesByDate
149142
case .selectDay(let day):
150143
if let day, state.selectedDay?.date == day.date {
151144
state.selectedDay = nil
@@ -166,11 +159,11 @@ final class ProfileViewModel: Store {
166159
guard canMove(to: nextQuarterStart, calendar: calendar, today: today) else { break }
167160

168161
state.selectedQuarterStart = nextQuarterStart
162+
state.completionQuarter = nil
163+
state.dayActivitiesByDate = [:]
169164
state.selectedDay = nil
170165
state.selectedActivityForSheet = nil
171-
if state.completionQuarterCache[nextQuarterStart] == nil {
172-
effects = [.fetchCompletionQuarter(nextQuarterStart)]
173-
}
166+
effects = [.fetchCompletionQuarter(nextQuarterStart)]
174167
case .toggleActivityType(let activityType):
175168
if state.selectedActivityTypes.contains(activityType), state.selectedActivityTypes.count == 1 {
176169
break
@@ -212,7 +205,14 @@ final class ProfileViewModel: Store {
212205
let todos = try await fetchQuarterTodos(from: quarterStart)
213206
let months = makeCompletionMonths(from: todos, quarterStart: quarterStart)
214207
let quarter = ProfileCompletionQuarter(quarterStart: quarterStart, months: months)
215-
send(.setCompletionQuarter(quarter, todos))
208+
let dayActivitiesByDate = makeDayActivitiesByDate(from: todos)
209+
send(
210+
.setCompletionQuarter(
211+
quarterStart: quarterStart,
212+
quarter: quarter,
213+
dayActivitiesByDate: dayActivitiesByDate
214+
)
215+
)
216216
} catch {
217217
send(.setAlert(true))
218218
}
@@ -235,6 +235,35 @@ final class ProfileViewModel: Store {
235235
}
236236

237237
private extension ProfileViewModel {
238+
func makeDayActivitiesByDate(from todos: [Todo]) -> [Date: [ProfileSelectedDayActivity]] {
239+
var activitiesByDate: [Date: [ProfileSelectedDayActivity]] = [:]
240+
241+
for todo in todos {
242+
let createdDay = calendar.startOfDay(for: todo.createdAt)
243+
let completedDay = todo.isCompleted ? calendar.startOfDay(for: todo.updatedAt) : nil
244+
245+
activitiesByDate[createdDay, default: []].append(
246+
ProfileSelectedDayActivity(
247+
todo: todo,
248+
showsCreated: true,
249+
showsCompleted: completedDay == createdDay
250+
)
251+
)
252+
253+
if let completedDay, completedDay != createdDay {
254+
activitiesByDate[completedDay, default: []].append(
255+
ProfileSelectedDayActivity(
256+
todo: todo,
257+
showsCreated: false,
258+
showsCompleted: true
259+
)
260+
)
261+
}
262+
}
263+
264+
return activitiesByDate
265+
}
266+
238267
func setAlert(
239268
_ state: inout State,
240269
isPresented: Bool

0 commit comments

Comments
 (0)