This is Model and View Model. I am using UserDefaults for saving data.
import Foundation
struct Item: Identifiable, Codable {
var id = UUID()
var name: String
var int: Int
var date = Date()
}
class ItemViewModel: ObservableObject {
@Published var ItemList = [Item] ()
init() {
load()
}
func load() {
guard let data = UserDefaults.standard.data(forKey: "ItemList"),
let savedItems = try? JSONDecoder().decode([Item].self, from: data) else { ItemList = []; return }
ItemList = savedItems
}
func save() {
do {
let data = try JSONEncoder().encode(ItemList)
UserDefaults.standard.set(data, forKey: "ItemList")
} catch {
print(error)
}
}
}
and this is the view. I am tryng too add new item and sort them by date. After that adding numbers on totalNumber. I tried .sorted() in ForEach but its not work for sort by date. and I try to create a func for adding numbers and that func is not work thoo.
import SwiftUI
struct ContentView: View {
@State private var name = ""
@State private var int = 0
@AppStorage("TOTAL_NUMBER") var totalNumber = 0
@StateObject var VM = ItemViewModel()
var body: some View {
VStack(spacing: 30) {
VStack(alignment: .leading) {
HStack {
Text("Name:")
TextField("Type Here...", text: $name)
}
HStack {
Text("Number:")
TextField("Type Here...", value: $int, formatter: NumberFormatter())
}
Button {
addItem()
VM.save()
name = ""
int = 0
} label: {
Text ("ADD PERSON")
}
}
.padding()
VStack(alignment: .leading) {
List(VM.ItemList) { Item in
Text(Item.name)
Text("\(Item.int)")
Text("\(Item.date, format: .dateTime.day().month().year())")
}
Text("\(totalNumber)")
.padding()
}
}
}
func addItem() {
VM.ItemList.append(Item(name: name, int: int))
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
CodePudding user response:
First of all please name variables always with starting lowercase letter for example
@Published var itemList = [Item] ()
@StateObject var vm = ItemViewModel()
To sort the items by date in the view model replace
itemList = savedItems
with
itemList = savedItems.sorted{ $0.date < $1.date }
To show the sum of all int
properties of the today items add a @Published var totalNumber
in the view model and a method to calculate the value. Call this method in load
and save
class ItemViewModel: ObservableObject {
@Published var itemList = [Item] ()
@Published var totalNumber = 0
init() {
load()
}
func load() {
guard let data = UserDefaults.standard.data(forKey: "ItemList"),
let savedItems = try? JSONDecoder().decode([Item].self, from: data) else { itemList = []; return }
itemList = savedItems.sorted{ $0.date < $1.date }
calculateTotalNumber()
}
func save() {
do {
let data = try JSONEncoder().encode(itemList)
UserDefaults.standard.set(data, forKey: "ItemList")
calculateTotalNumber()
} catch {
print(error)
}
}
func calculateTotalNumber() {
let todayItems = itemList.filter{ Calendar.current.isDateInToday($0.date) }
totalNumber = todayItems.map(\.int).reduce(0, )
}
}
In the view delete the @AppStorage
line because the value is calculated on demand and replace
Text("\(totalNumber)")
with
Text("\(vm.totalNumber)")