UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

SOLVED: Project day 47- View isn't updated after updating the ObservableObject property

Forums > 100 Days of SwiftUI

Hi! I would be grateful for any anvice how to fix my Habit Tracker project. At the moment I'm able to update how many times the activity was done and it changes when I go back to the list but I cannot see any updates on the Activity View in real time (In the "Completed XXX times" Text View). Here is my code:

//
//  ContentView.swift
//  HabitTracker
//
//  Created by Anna Nakayama on 2020/12/04.
//

import SwiftUI

struct Activity: Identifiable, Codable {
    private(set) var id = UUID()
    let name: String
    let description: String
    var doneCount: Int
}

class Activities: ObservableObject {
    @Published var activities: [Activity] {
        didSet {
            let encoder = JSONEncoder()
            if let encoded = try? encoder.encode(activities) {
                UserDefaults.standard.set(encoded, forKey: "Activities")
            }
        }
    }

    init() {
        if let activities = UserDefaults.standard.data(forKey: "Activities") {
            let decoder = JSONDecoder()
            if let decoded = try? decoder.decode([Activity].self, from: activities) {
                self.activities = decoded
                return
            }
        }
        self.activities = []
    }

    func updateDoneCount(index: Int) {
        activities[index].doneCount += 1
    }
}

struct ContentView: View {
    @ObservedObject var myActivities = Activities()
    @State private var showingAddActivity = false

    var body: some View {
        NavigationView {
            List {
                ForEach(myActivities.activities.indices, id: \.self) { index in
                    NavigationLink(destination: ActivityView( activities: myActivities, index: index)) {
                        HStack {
                            VStack(alignment: .leading) {
                                Text(self.myActivities.activities[index].name)
                                    .font(.headline)
                            }
                            Spacer()
                            Text("Completed \(self.myActivities.activities[index].doneCount) times")
                        }
                    }
                }
                .onDelete(perform: removeActivity)
            }
            .navigationTitle("Activity Tracker")
            .navigationBarItems(leading: EditButton(), trailing: Button(action: {
                self.showingAddActivity = true
            }) {    
                Image(systemName: "plus")
            })
            .sheet(isPresented: $showingAddActivity) {
                AddView(activities: self.myActivities)
            }
        }
    }

    func removeActivity(at offsets: IndexSet) {
        self.myActivities.activities.remove(atOffsets: offsets)
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
//
//  ActivityView.swift
//  HabitTracker
//
//  Created by Anna Nakayama on 2020/12/07.
//

import SwiftUI

struct ActivityView: View {
    var activities: Activities
    var index: Int

    var body: some View {
        VStack(alignment: .center) {
            Text(activities.activities[index].name)
                .font(.title)
                .foregroundColor(.purple)
                .padding()
            Text(activities.activities[index].description)
            Text("Completed \(activities.activities[index].doneCount) times")
                .padding()

            Button(action:{ self.activities.updateDoneCount(index: self.index)}) {
                Text("Complete!")
                    .padding()
                    .foregroundColor(.white)
                    .background(Color.purple)
                    .font(.title)
                    .cornerRadius(40)
            }
            .navigationBarTitle(Text("My activity"), displayMode: .inline)
        }
    }
}

struct ActivityView_Previews: PreviewProvider {
    static var previews: some View {
        let activities = Activities()
        ActivityView(activities: activities, index: 0)
    }
}

3      

hi,

in ActivityView, you need @ObservedObject var activities: Activities.

touching the Complete button in ActivityView does indeed cause the activities object (class) to signal that a change has been made to its @Published array; but you need @ObservedObject to make sure that your ActivityView is listening for the signal so that it can redraw.

hope that helps,

DMG

4      

@delawaremathguy Thanks so much for your help! Worked like a charm :)

3      

Hacking with Swift is sponsored by Essential Developer

SPONSORED Join a FREE crash course for mid/senior iOS devs who want to achieve an expert level of technical and practical skills – it’s the fast track to being a complete senior developer! Hurry up because it'll be available only until April 28th.

Click to save your free spot now

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.