728x90
SMALL
이전 글에서는 MVVM 구조에서의 TransactionViewModel 전반 구조와 초기화 방식에 대해 정리했습니다.
이번 글에서는 그 ViewModel 내부에서 수행되는 데이터 읽기, 수정, 삭제 기능을 소개합니다.
✳️ 전체 흐름 요약
모든 데이터 처리는 TransactionCoreDataManager를 통해 Core Data와 통신하며, Combine을 통해 비동기 스트림을 처리합니다.
📌 관련 구조:
- TransactionViewModel → View에서 호출
- TransactionCoreDataManager → Core Data와 실제 상호작용
- @Published → UI 바인딩을 위한 데이터 상태 반영
📖 Read - 거래 내역 불러오기
✅ 모든 거래 내역 불러오기 (readAllTransactions())
func readAllTransactions() {
transactionManager.readAllTransaction()
.sink(receiveCompletion: { completion in
switch completion {
case .finished:
break
case .failure(let error):
self.errorMessage = error.localizedDescription
}
}, receiveValue: { [weak self] savedTransaction in
self?.transactions = savedTransaction
})
.store(in: &cancellables)
}
- Core Data에서 전체 거래 내역을 불러와 transactions 배열에 저장합니다.
- 실패 시 에러 메시지를 바인딩하여 View에 표시할 수 있습니다.
💡 홈 화면, 월별 통계 화면 등에서 사용됩니다.
🔍 특정 거래 불러오기 (readByIDTransaction())
func readByIDTransaction(by id: UUID) {
transactionManager.readTransactionByID(by: id)
.receive(on: DispatchQueue.main)
.sink(receiveCompletion: { [weak self] completion in
if case .failure(let error) = completion {
self?.errorMessage = error.localizedDescription
}
}, receiveValue: { [weak self] readedTransaction in
self?.transaction = readedTransaction
})
.store(in: &cancellables)
}
- 특정 UUID에 해당하는 거래 내역 하나만 읽어옵니다.
- 편집 모드 진입 시 기존 정보를 불러와 form에 채워넣을 때 사용됩니다.
🛠️ Update - 거래 내역 수정하기
func updateTransaction() {
guard let transaction = transaction else {
errorMessage = "Transaction no data"
return
}
transactionManager.updateTransaction(transaction)
.receive(on: DispatchQueue.main)
.sink(receiveCompletion: { [weak self] completion in
if case .failure(let error) = completion {
self?.errorMessage = error.localizedDescription
}
}, receiveValue: { [weak self] updated in
self?.transaction = updated
})
.store(in: &cancellables)
}
- 사용자가 변경한 값을 transaction에 반영한 뒤 저장합니다.
- 성공 시 최신 상태로 ViewModel의 값을 갱신합니다.
- Combine을 통해 UI는 자동으로 반영됩니다.
🧠 이점: View와 Model 간 동기화 유지 + 재사용 가능성 ↑
🗑️ Delete - 거래 내역 삭제하기
func deleteTransaction(by id: UUID) {
transactionManager.deleteTransaction(id: id)
.receive(on: DispatchQueue.main)
.sink(receiveCompletion: { [weak self] completion in
if case .failure(let error) = completion {
self?.errorMessage = "삭제 실패: \(error.localizedDescription)"
}
}, receiveValue: { [weak self] success in
guard let self = self else { return }
if success {
print("✅ ViewModel: CoreData 삭제 성공")
// 배열에서 삭제
self.transactions.removeAll { $0.id == id }
// 현재 선택된 트랜잭션도 초기화
if self.transaction?.id == id {
self.transaction = nil
}
} else {
self.errorMessage = "삭제 실패: 알 수 없는 이유"
}
})
.store(in: &cancellables)
}
- 해당 거래 내역을 Core Data에서 삭제하고, ViewModel에서도 상태를 정리합니다.
- 삭제 성공 시:
- 목록에서 제거
- 현재 선택된 거래(transaction)도 초기화
- 삭제 실패 시 에러 메시지 노출
🔁 상태 흐름 다이어그램 (간단 정리)
[View Action]
↓
[TransactionViewModel 함수 호출]
↓
[TransactionCoreDataManager 통해 Core Data 처리]
↓
[Combine 통해 결과 수신 → @Published 업데이트]
↓
[UI 자동 반영]
💡 ViewModel이 Combine + Core Data를 감싸는 이유?
- Combine을 직접 View에서 쓰지 않고, ViewModel에서 처리하면 코드가 응집도 높고 테스트 용이함
- Core Data의 복잡한 처리 로직을 View에서 분리할 수 있어 MVVM의 역할 분리가 명확해짐
- 상태 변화는 모두 @Published로 반영되어 SwiftUI 또는 UIKit 모두에서 효율적으로 UI 갱신 가능
728x90
LIST
'Project > ReceiptMind' 카테고리의 다른 글
| 💰 Swift reduce 완전 정복: totalAmount() 메서드로 배우는 누적 합계 계산 (0) | 2025.08.03 |
|---|---|
| 💡 Swift에서 배열 필터링하기: filteredTransactions 메서드 완전 해부 (0) | 2025.08.03 |
| 💸 iOS MVVM 가계부 앱 - ViewModel(TransactionViewModel) 구조 완벽 정리 (0) | 2025.08.03 |
| 📦 iOS MVVM 가계부 앱 - Core Data 삭제(Delete) + 이미지 제거까지 정리 (1) | 2025.08.02 |
| 📚 iOS MVVM 가계부 앱 - Core Data 수정(Update) + 이미지까지 깔끔히 반영하는 법 (1) | 2025.08.02 |