Home > Mobile >  Sorting items by date. And adding numbers from today
Sorting items by date. And adding numbers from today

Time:11-12

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)")
  • Related