Home > Software engineering >  Data is not saved or load because of i am call the data from another pages
Data is not saved or load because of i am call the data from another pages

Time:11-13

Model

I have different variables in Travel.

import Foundation

struct Travel: Identifiable, Codable {
    var id = UUID()
    var name: String
    var date = Date()
    var location: String
    var isFav: Bool
    var score: Float
    var comment: String
}

View model

I load and save data with UserDefaults. Always its work but in this model not.

import Foundation


class TravelViewModel: ObservableObject {
    @Published var travelList = [Travel] ()
    @Published var travelled = 0
    
    init(){
        load()
    }
    
    func load() {
        guard let data = UserDefaults.standard.data(forKey: "travelList"),
              let savedTravels = try? JSONDecoder().decode([Travel].self, from: data) else { travelList = []; return }
        
        travelList = savedTravels
    }
    
    func save() {
        do {
            let data = try JSONEncoder().encode(travelList)
            UserDefaults.standard.set(data, forKey: "travelList")
        } catch {
            print(error)
        }
    }
    
}

Adding Item View

I have addItems func and use this func in addItem button.

import SwiftUI

struct AddTravelView: View {
    
    @StateObject var VM = TravelViewModel()
    
    @State var name = ""
    @State var location = ""
    @State var isFav = false
    @State var score = 0.00
    @State var comment = ""
    
    var body: some View {
        VStack {
            ZStack {
                Rectangle()
                    .fill(.black.opacity(0.2))
                    .cornerRadius(20)
                    .frame(width: 350, height: 350)
                VStack{
                    HStack {
                        Text("Name:")
                            .font(.system(size: 16 , weight: .medium))
                        TextField("Type..", text: $name)
                    }
                    HStack {
                        Text("Location:")
                            .font(.system(size: 16 , weight: .medium))
                        TextField("Type..", text: $location)
                    }
                    HStack {
                        Text("Score: \(Int(score))")
                            .font(.system(size: 16 , weight: .medium))
                        Slider(value: $score, in: 0...10, step: 1)
                    }
                    Spacer()
                    
                    ZStack(alignment: .topLeading) {
                        Rectangle()
                            .fill(.white)
                            .cornerRadius(20)
                            .frame(height: 200)
                        VStack(alignment: .leading) {
                            TextField("Comment...", text: $comment, axis: .vertical)
                        }.padding()
                    }
                }
                .padding()
                .frame(width: 300, height: 200)
            }
            
            Button {
                addTravel()
            } label: {
                ZStack{
                    Rectangle()
                        .fill(.black.opacity(0.2))
                        .cornerRadius(20)
                        .frame(width: 350 , height: 100)
                        
                    
                    Text("ADD TRAVEL")
                        .font(.system(size: 25, weight: .medium, design: .monospaced))
                        .foregroundColor(.black)
                }.padding()
            }

            
        }
    }
    
    func addTravel(){
        VM.travelList.append(Travel(name: name, location: location, isFav: isFav, score: Float(score), comment: comment))
    }
    
}

struct AddTravelView_Previews: PreviewProvider {
    static var previews: some View {
        AddTravelView()
    }
}

Recent Adds view

In this page i wanna see Items i add before

import SwiftUI

struct RecentTravels: View {
    
    @StateObject var VM = TravelViewModel()
    
    var body: some View {
        VStack {
            ForEach(VM.travelList) {Travel in
                HStack{
                    Image(systemName: "questionmark")
                        .frame(width: 50, height: 50)
                        .padding()
                        .overlay {
                            RoundedRectangle(cornerRadius: 5)
                                .stroke(.black, lineWidth: 2)
                        }
                    VStack(alignment: .leading) {
                        Text(Travel.name)
                            .font(.subheadline)
                            .bold()
                            .lineLimit(1)
                        Text("\(Travel.date)")
                            .font(.footnote)
                            .opacity(0.9)
                            .lineLimit(1)
                    }
                    
                    Spacer()
                    VStack {
                        Image(systemName: "heart")
                        Spacer()
                        Text("\(Travel.score)")
                    }
                    .frame(height: 50)
                    .font(.system(size: 22))
                    
                }
            }
        }
    }
}

struct RecentTravels_Previews: PreviewProvider {
    static var previews: some View {
        RecentTravels()
    }
}

And ContentView

and calling those 2 views in ContentView.

import SwiftUI

struct ContentView: View {
    
    @StateObject var VM = TravelViewModel()
    
    var body: some View {
        VStack {
            
            AddTravelView()
            
            RecentTravels()
        }
        .padding()
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

When i write the all code in only ContentView is work but when i call another pages its not work. Usually it was work when i presss add item button and restart app but now its nothing. Its not work even restart the app.

CodePudding user response:

The problem you have is that you have multiple VM, that have no relations to each other. You must not have more than one source of truth in @StateObject var VM = TravelViewModel().

Keep the one you have in ContentView, and pass it to the other view like this: VStack {....}.environmentObject(VM).

In your AddTravelView and RecentTravels , add @EnvironmentObject var VM: TravelViewModel instead of @StateObject var VM = TravelViewModel().

Have a look at this link, it gives you some good examples of how to manage data in your app:
https://developer.apple.com/documentation/swiftui/managing-model-data-in-your-app

  • Related