Learn Courses My Dashboard

Help with Favorites Button

I am working on a music catalog app and while I have the bulk it working I want to be able to mark an album as a favorite from the row view as well as the detail view. This function works when marking an album as a favorite on the row view and it shows correctly when moving to the detail view. The issue I am having is if I mark an album on the detail view it doesn’t refresh the row view when moving back to the row view. The below code is a stripped down version of what I am trying to do. View1 represents the row view and View2 represents the detail view.

I am sure it is something really simple that I am missing but I am still fairly new to iOS development and kind of running out of ideas. I am also using UserDefaults instead of AppStorage as it seemed easier to pass a variable as the key to UserDefaults than it was to AppStorage and the views are separate files in my main project but for the sake of the test project/code it was easier to combine them for testing. Anyway, any help or guidance would be greatly appreciated.

import SwiftUI

struct View1: View {
    
    var body: some View {
        NavigationView {
            VStack {
                NavigationLink(
                    destination: View2(),
                    label: {
                        let myKey = "item1"
                        let favoritesStatus = UserDefaults.standard.bool(forKey: myKey)
                        FavoritesView(isFavorites: myKey, favoritesStatus: favoritesStatus)
                            .padding(.horizontal, 30)
                        Text("Go To View 2")
                })
            }
        }
    }
}

struct View2: View {
    var body: some View {
        let myKey = "item1"
        let favoritesStatus = UserDefaults.standard.bool(forKey: myKey)
        VStack {
            FavoritesView(isFavorites: myKey, favoritesStatus: favoritesStatus)
                .padding(.horizontal, 30)
        }
    }
}

struct FavoritesView: View {
    @State var isFavorites: String
    @State var favoritesStatus: Bool
    
    var body: some View {
        ZStack {
            Image(systemName: favoritesStatus ? "star.fill" : "star" )
                .foregroundColor(.yellow)
                .font(.system(size: 20))
            
            Image(systemName: "star")
                .font(.system(size: 20))
                .foregroundColor(.black)
        }
        .onTapGesture {
            updateFavoritesStatus()
        }
    }
    
    func updateFavoritesStatus() {
        favoritesStatus = !favoritesStatus
        UserDefaults.standard.set(favoritesStatus, forKey: isFavorites)
    }
    
}

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

I would recommend using App Storage for this exact reason

SwiftUI has a dedicated property wrapper for reading values from UserDefaults , which will automatically reinvoke your view’s body property when the value changes. That is, this wrapper effectively watches a key in UserDefaults , and will refresh your UI if that key changes

https://www.hackingwithswift.com/quick-start/swiftui/what-is-the-appstorage-property-wrapper

Otherwise if you don’t want to, you should be able to add an onDisappear modifier to your first view when the view2 is dismissed and call a function to update your model