반응형
항상하는 프로젝트의 마지막! 업그레이드 편이다.
1. 사용자의 통화로 바꾸세요!
//ContentView, AddView 의 통화만 바꿔주면된다!
Text(item.amount, format: .currency(code: "KRW"))
2. 금액에 따라 ContentView에서 표기를 다르게 하세요!
처음에는 단순이 ContentView 내 List에 background modifier 를 추가해서 변경하려 했지만! 로직이 들어가면 안되니 안되고...
변수를 선언해서 판단하게 했는데!
리스트가 추가될때마나 색을 나타내는 배열이 필요하더라...
그래서 ExpenseItem 구조체에 색을 나타내는 변수를 추가 했는데!
파일 저장시 Color는 저장값으로 안되어 있었다..
그래서 저장시에는 colorIndex를 저장하고, (구조체에도 Int형으로 추가 )
보여줄때 정해진 색으로 보여지게 구현했다!
전체 소스이다!
//
// ContentView.swift
// iExpense
//
// Created by HanTJ on 12/1/24.
//
import SwiftUI
struct ExpenseItem: Identifiable, Codable { //저장을 위한 Codable
var id = UUID() //UUID자동생성!
let name: String
let type: String
let amount: Double
let colorIndex: Int
}
@Observable
class Expenses {
var items = [ExpenseItem]() {
didSet {
// persistent 저장!
if let encoded = try? JSONEncoder().encode(items) {
UserDefaults.standard.set(encoded, forKey: "Items")
}
}
}
//처음 클래스 생성시 persistent 를 복원
init() {
if let savedItems = UserDefaults.standard.data(forKey: "Items") {
if let decodedItems = try? JSONDecoder().decode([ExpenseItem].self, from:savedItems) { //self는 꼭 써야하는건가..
items = decodedItems
return
}
}
items = [] //에러방지! 오류나면 빈값으로 초기화
}
}
struct ContentView: View {
@State private var expenses = Expenses()
@State private var showingAddExpense = false
let colors:[Color] = [.white, .orange, .red ]
var body: some View {
NavigationStack {
List {
ForEach(expenses.items) { item in //id항목 않써줘도 된다 why? Identifiable 프로토콜을 구현했기 때문에!
HStack {
VStack {
Text(item.name)
.font(.headline)
Text(item.type)
}
Spacer()
Text(item.amount, format: .currency(code: "KRW"))
}
.background(colors[item.colorIndex])
}
.onDelete(perform: removeItems)
}
.navigationTitle("iExpense")
.toolbar {
Button("Add Expense", systemImage: "plus") {
showingAddExpense = true
}
}
.sheet(isPresented: $showingAddExpense) {
AddView(expenses: expenses)
}
}
}
//delete item의 공식같이 익혀두자.
func removeItems(at offsets: IndexSet) {
expenses.items.remove(atOffsets: offsets)
}
}
#Preview {
ContentView()
}
3. Personal 과 Business 를 구분해서 보여주자!
//
// ContentView.swift
// iExpense
//
// Created by HanTJ on 12/1/24.
//
import SwiftUI
struct ExpenseItem: Identifiable, Codable { //저장을 위한 Codable
var id = UUID() //UUID자동생성!
let name: String
let type: String
let amount: Double
let colorIndex: Int
}
@Observable
class Expenses {
var items = [ExpenseItem]() {
didSet {
// persistent 저장!
if let encoded = try? JSONEncoder().encode(items) {
UserDefaults.standard.set(encoded, forKey: "Items")
}
}
}
//처음 클래스 생성시 persistent 를 복원
init() {
if let savedItems = UserDefaults.standard.data(forKey: "Items") {
if let decodedItems = try? JSONDecoder().decode([ExpenseItem].self, from:savedItems) { //self는 꼭 써야하는건가..
items = decodedItems
return
}
}
items = [] //에러방지! 오류나면 빈값으로 초기화
}
}
struct ContentView: View {
@State private var expenses = Expenses()
@State private var showingAddExpense = false
let colors:[Color] = [.white, .orange, .red ]
var body: some View {
NavigationStack {
List {
GroupBox("Personal") {
ForEach(expenses.items.filter { $0.type == "Personal" } ) { item in //id항목 않써줘도 된다 why? Identifiable 프로토콜을 구현했기 때문에!
HStack {
VStack {
Text(item.name)
.font(.headline)
Text(item.type)
}
Spacer()
Text(item.amount, format: .currency(code: "KRW"))
}
.background(colors[item.colorIndex])
}
.onDelete(perform: removeItems)
}
GroupBox("Business") {
ForEach(expenses.items.filter { $0.type == "Business" }) { item in //id항목 않써줘도 된다 why? Identifiable 프로토콜을 구현했기 때문에!
HStack {
VStack {
Text(item.name)
.font(.headline)
Text(item.type)
}
Spacer()
Text(item.amount, format: .currency(code: "KRW"))
}
.background(colors[item.colorIndex])
}
.onDelete(perform: removeItems)
}
}
.navigationTitle("iExpense")
.toolbar {
Button("Add Expense", systemImage: "plus") {
showingAddExpense = true
}
}
.sheet(isPresented: $showingAddExpense) {
AddView(expenses: expenses)
}
}
}
//delete item의 공식같이 익혀두자.
func removeItems(at offsets: IndexSet) {
expenses.items.remove(atOffsets: offsets)
}
}
#Preview {
ContentView()
}
여러가지 시도를 해보다가, GroupBox 로 구분을 하고,
ForEach로 루핑시 배열의 filter 함수를 이용해서 구분해 두 그룹으로 보여줬다!
하지만 역시 문제에 나와있는것처럼 삭제부분이 동작을 안한다 --;;
여기까지 하고 패스 ㄱㄱ
반응형