Skip to content

Commit

Permalink
Merge pull request #134 from DeveloperAcademy-POSTECH/Refactor/#131
Browse files Browse the repository at this point in the history
[Refator/#131] UserDefaults -> SwiftData
  • Loading branch information
SSSiye authored Jan 24, 2025
2 parents 40d3b59 + 8ed0499 commit ba90c0e
Show file tree
Hide file tree
Showing 11 changed files with 117 additions and 86 deletions.
4 changes: 2 additions & 2 deletions PennyPack.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -584,7 +584,7 @@
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_ASSET_PATHS = "\"PennyPack/Preview Content\"";
DEVELOPMENT_TEAM = R83JF9K5WA;
DEVELOPMENT_TEAM = 7P4U6S44RJ;
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = PennyPack/Info.plist;
Expand Down Expand Up @@ -624,7 +624,7 @@
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_ASSET_PATHS = "\"PennyPack/Preview Content\"";
DEVELOPMENT_TEAM = R83JF9K5WA;
DEVELOPMENT_TEAM = 7P4U6S44RJ;
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = PennyPack/Info.plist;
Expand Down
18 changes: 17 additions & 1 deletion PennyPack/App/PennyPackApp.swift
Original file line number Diff line number Diff line change
@@ -1,11 +1,27 @@
import SwiftUI
import SwiftData

@main
struct PennyPackApp: App {

var modelContainer: ModelContainer = {
let schema = Schema([ListManager.self, ShoppingManager.self]) // ModelContainer를 생성하려면 우선 사용할 모델들을 스키마로 만들어준다.
let modelConfiguration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: false)
// ModelConfiguration을 생성해 모델 관리 규칙을 설정해준다.
// ModelConfiguration 옵션으로는 여러 가지가 있는데, (프리뷰 등에서 데이터를 메모리 상에서만 관리할지 여부를 결정하는) inStoredInMemoryOnly, (CloudKit을 사용할 때 데이터베이스를 설정하는) cloudKitbataBase 등이 있다.

do {
return try ModelContainer(for: schema, configurations: [modelConfiguration])
} catch {
fatalError("Could not create ModelContainer: \(error)")
}
// 마지막으로 이렇게 만든 Schema와 ModelConfiguration을 사용해 ModelContainer를 만들어준다.
}()

var body: some Scene {
WindowGroup {
MainView(mainViewModel: MainViewModel(shoppingManager: ShoppingManager(), listManager: ListManager()))
MainView(mainViewModel: MainViewModel(shoppingManager: [ShoppingManager()], listManager: [ListManager()]))
}
.modelContainer(modelContainer)
}
}
24 changes: 4 additions & 20 deletions PennyPack/Magagers/ListManager.swift
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import Foundation
import SwiftData

class ListManager: ObservableObject {
@Published var shoppingList: [ShoppingList] = []
@Model
class ListManager {
@Relationship var shoppingList: [ShoppingList] = []

init() {
loadShoppingListFromUserDefaults()
}

// MARK: 리스트에 새 값 추가 함수
Expand All @@ -24,24 +25,7 @@ class ListManager: ObservableObject {

func removeList(at offsets: IndexSet) {
shoppingList.remove(atOffsets: offsets)
saveShoppingListToUserDefaults()

print("Updated shoppingList: \(shoppingList)")
}

// MARK: 데이터를 인코딩하고 UserDefaults에 저장
func saveShoppingListToUserDefaults() {
if let encoded = try? JSONEncoder().encode(shoppingList) {
UserDefaults.standard.set(encoded, forKey: "shoppingList")
}
}

func loadShoppingListFromUserDefaults() {
if let savedData = UserDefaults.standard.data(forKey: "shoppingList") {
if let saveLists = try? JSONDecoder().decode([ShoppingList].self, from: savedData) {
self.shoppingList = saveLists
}
}
}

}
32 changes: 8 additions & 24 deletions PennyPack/Magagers/ShoppingManager.swift
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import Foundation
import SwiftData

class ShoppingManager:ObservableObject {
@Published var receiptDate: [ReceiptDate] = []
@Published var cartItem: [CartItem] = []
@Published var selectedReceiptDate: ReceiptDate?
@Model
class ShoppingManager {
var receiptDate: [ReceiptDate] = []
var cartItem: [CartItem] = []
var selectedReceiptDate: ReceiptDate?

@Published var nowBudget: Int?
@Published var nowPlace: String = ""
var nowBudget: Int?
var nowPlace: String = ""

init(){
loadShoppingListFromUserDefaults()
}
// MARK: 리스트에 새 값 추가 함수
func addNewCartItem(korName: String, frcName: String, quantity: Int, korUnitPrice: Int, frcUnitPrice: Double) -> CartItem {
Expand All @@ -23,25 +24,8 @@ class ShoppingManager:ObservableObject {
print("Updated shoppingList: \(cartItem)")
}

// MARK: 데이터를 인코딩하고 UserDefaults에 저장
func saveShoppingListToUserDefaults() {
if let encoded = try? JSONEncoder().encode(receiptDate) {
UserDefaults.standard.set(encoded, forKey: "receiptDate")
}

print("save 됨")
}

// MARK: UserDefaults에서 데이터를 불러오기
func loadShoppingListFromUserDefaults() {
if let savedData = UserDefaults.standard.data(forKey: "receiptDate") {
if let saveLists = try? JSONDecoder().decode([ReceiptDate].self, from: savedData){
receiptDate = saveLists
}
}
print("load 됨")
print("*******************************")

for item in receiptDate {
print("날짜: \(item.date)")
for index in item.items{
Expand Down
6 changes: 3 additions & 3 deletions PennyPack/ViewModels/CartViewModel.swift
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import Foundation
import SwiftUI

class CartViewModel: ObservableObject{
@Published var shoppingManager: ShoppingManager
@Published var listManager: ListManager
class CartViewModel: ObservableObject {
@Bindable var shoppingManager: ShoppingManager
@Bindable var listManager: ListManager

@Published var recognizedText = ""
@Published var isAlert: Bool = false
Expand Down
9 changes: 5 additions & 4 deletions PennyPack/ViewModels/MainViewModel.swift
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import Foundation
import SwiftUI
import SwiftData

class MainViewModel: ObservableObject{
@Published var shoppingManager: ShoppingManager
@Published var listManager: ListManager
class MainViewModel: ObservableObject {
@Published var shoppingManager: [ShoppingManager]
@Published var listManager: [ListManager]

init(shoppingManager: ShoppingManager, listManager: ListManager) {
init(shoppingManager: [ShoppingManager], listManager: [ListManager]) {
self.shoppingManager = shoppingManager
self.listManager = listManager
}
Expand Down
9 changes: 5 additions & 4 deletions PennyPack/Views/CartView/CartView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import SwiftUI
struct CartView: View {
@EnvironmentObject var pathRouter: PathRouter
@Environment(\.dismiss) var dismiss
@ObservedObject var cartViewModel: CartViewModel
@StateObject var cartViewModel: CartViewModel

@FocusState var focusedField: Field?

Expand Down Expand Up @@ -213,7 +213,7 @@ struct CartView: View {
.foregroundColor(.pBlue)
}
}
ToolbarItem(placement: .principal){
ToolbarItem(placement: .principal) {
Text("장보기")
.font(.PTitle2)
.foregroundColor(.pWhite)
Expand All @@ -226,7 +226,7 @@ struct CartView: View {
cartViewModel.listManager.shoppingList[index].isPurchase = cartViewModel.listManager.shoppingList[index].isChoise
}

cartViewModel.listManager.saveShoppingListToUserDefaults()
// cartViewModel.listManager.saveShoppingListToUserDefaults()
}) {
Text("종료")
.foregroundColor(.pBlue)
Expand Down Expand Up @@ -265,7 +265,8 @@ struct CartView: View {
}
.hideKeyboard()

HStack(spacing: 0){ TextField("1", text: Binding(
HStack(spacing: 0){
TextField("1", text: Binding(
get: { String(cartViewModel.shoppingManager.cartItem[index].quantity) },
set: { newValue in
if let intValue = Int(newValue) {
Expand Down
2 changes: 1 addition & 1 deletion PennyPack/Views/CartView/CustomAlertView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ struct CustomAlertView: View {

cartViewModel.shoppingManager.receiptDate.append(receiptDate)
cartViewModel.shoppingManager.cartItem = []
cartViewModel.shoppingManager.saveShoppingListToUserDefaults()
cartViewModel.shoppingManager

} label: {
Text("종료하기")
Expand Down
3 changes: 2 additions & 1 deletion PennyPack/Views/Components/DropdownListView.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import SwiftUI

struct DropdownListView: View {
@ObservedObject var listManager: ListManager
@Environment(\.modelContext) private var context
@Bindable var listManager: ListManager

var body: some View {
VStack(spacing: 0){
Expand Down
77 changes: 59 additions & 18 deletions PennyPack/Views/MainView/ListView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,58 @@ struct ListView: View {
var body: some View {
VStack{
List{
ForEach($mainViewModel.listManager.shoppingList, id: \.id){ $item in
if !item.isPurchase {
TextField("마트에서 살 물건을 이곳에 적어주세요.", text: $item.title)
if let firstListManager = mainViewModel.listManager.first {
// ForEach($mainViewModel.listManager.shoppingList, id: \.id){ $item in
// if !item.isPurchase {
// TextField("마트에서 살 물건을 이곳에 적어주세요.", text: $item.title)
// .onSubmit {
// mainViewModel.listManager
// }
// }
// }
ForEach(firstListManager.shoppingList, id: \.id) { item in
if !item.isPurchase {
TextField("마트에서 살 물건을 이곳에 적어주세요.", text: Binding(
get: { item.title },
set: { newValue in
if let index = firstListManager.shoppingList.firstIndex(where: { $0.id == item.id }) {
firstListManager.shoppingList[index].title = newValue
}
}
))
.onSubmit {
mainViewModel.listManager.saveShoppingListToUserDefaults()
// addList 호출은 데이터 모델로 위임
firstListManager.addList(title: "새로운 항목")
}
}
}
.onDelete { indexSet in
// 삭제 처리: firstListManager에서 해당 항목 삭제
firstListManager.removeList(at: indexSet)
}
} else {
Text("목록이 비어 있어요!")
}
.onDelete(perform: mainViewModel.listManager.removeList)
.listRowSeparator(.hidden)
.listRowBackground(
Rectangle()
.foregroundColor(.pWhite)
.cornerRadius(12)
)
// ForEach($mainViewModel.listManager.shoppingList, id: \.id){ $item in
// if !item.isPurchase {
// TextField("마트에서 살 물건을 이곳에 적어주세요.", text: $item.title)
// .onSubmit {
// mainViewModel.listManager
// }
// }
// }
// .onDelete(perform: mainViewModel.listManager.removeList)
// .listRowSeparator(.hidden)
// .listRowBackground(
// Rectangle()
// .foregroundColor(.pWhite)
// .cornerRadius(12)
// )
Button {
mainViewModel.listManager.addList(title: "")
// mainViewModel.listManager.addList(title: "")
if let firstListManager = mainViewModel.listManager.first {
firstListManager.addList(title: "새로운 항목")
}
} label: {
HStack{
Spacer()
Expand All @@ -36,20 +71,26 @@ struct ListView: View {
Spacer()
}
} .listRowSeparator(.hidden)
.listRowBackground(
Rectangle()
.foregroundColor(.pWhite)
.cornerRadius(12)
)
.listRowBackground(
Rectangle()
.foregroundColor(.pWhite)
.cornerRadius(12)
)
}
.listRowSpacing(8)
.listStyle(PlainListStyle())
.padding(.horizontal)
.background(.pLightGray)
.listRowSeparator(.hidden)
.listRowBackground(
Rectangle()
.foregroundColor(.pWhite)
.cornerRadius(12)
)
}
}
}

#Preview {
ListView(mainViewModel: MainViewModel(shoppingManager: ShoppingManager(), listManager: ListManager()))
ListView(mainViewModel: MainViewModel(shoppingManager: [ShoppingManager()], listManager: [ListManager()]))
}
19 changes: 11 additions & 8 deletions PennyPack/Views/MainView/MainView.swift
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import SwiftUI

struct MainView: View {
@Environment(\.modelContext) var modelContext
@StateObject var pathRouter = PathRouter()
@StateObject var mainViewModel = MainViewModel(shoppingManager: ShoppingManager(), listManager: ListManager())
@StateObject var mainViewModel = MainViewModel(shoppingManager: [ShoppingManager()], listManager: [ListManager()])

var body: some View {
NavigationStack(path: $pathRouter.path) {
Expand All @@ -17,7 +18,7 @@ struct MainView: View {
.foregroundColor(.pWhite)
Spacer()
NavigationLink(
destination: CalendarView(calendarViewModel: CalendarViewModel(shoppingManager: mainViewModel.shoppingManager, listManager: mainViewModel.listManager)),
destination: CalendarView(calendarViewModel: CalendarViewModel(shoppingManager: mainViewModel.shoppingManager.first!, listManager: mainViewModel.listManager.first!)),
label: {
Image(systemName: "calendar")
.font(.system(size: 24))
Expand Down Expand Up @@ -57,7 +58,9 @@ struct MainView: View {
VStack(spacing: 0){
HStack{
Button{
mainViewModel.listManager.addListShowcase(title: "")
// mainViewModel.listManager.addListShowcase(title: "")
mainViewModel.listManager.first?.addListShowcase(title: "") // 배열에서 첫 번째 ListManager 객체를 선택하여 메서드 호출

} label: {
Text("오늘의 장보기 리스트")
.font(.PTitle2)
Expand Down Expand Up @@ -117,23 +120,23 @@ struct MainView: View {

}
.onAppear{
mainViewModel.shoppingManager.loadShoppingListFromUserDefaults()
mainViewModel.listManager.loadShoppingListFromUserDefaults()
mainViewModel.shoppingManager
mainViewModel.listManager
}
.environmentObject(pathRouter)
.navigationDestination(for: NavigationRoute.self) { route in
switch route {
case .result:
VStack {
ResultView(resultViewModel: ResultViewModel(shoppingManager: mainViewModel.shoppingManager, listManager: mainViewModel.listManager))
ResultView(resultViewModel: ResultViewModel(shoppingManager: mainViewModel.shoppingManager.first!, listManager: mainViewModel.listManager.first!))
Button {
pathRouter.removeAll()
} label: {
Text("닫기")
}
}
case .cart:
CartView(cartViewModel: CartViewModel(shoppingManager: mainViewModel.shoppingManager, listManager: mainViewModel.listManager))
CartView(cartViewModel: CartViewModel(shoppingManager: mainViewModel.shoppingManager.first!, listManager: mainViewModel.listManager.first!))
}
}
}.navigationBarBackButtonHidden()
Expand All @@ -142,6 +145,6 @@ struct MainView: View {
}

#Preview {
MainView(mainViewModel: MainViewModel(shoppingManager: ShoppingManager(), listManager: ListManager()))
MainView(mainViewModel: MainViewModel(shoppingManager: [ShoppingManager()], listManager: [ListManager()]))
}

0 comments on commit ba90c0e

Please sign in to comment.