0

I have following problem, please refer to the code below. In the app I can create an Artist (@Model) and add some Albums (@Model) to it. These are stored and displayed as supposed.

When I'm launching the app again and navigating to an Artist to delete for instance an album (using .onDelete(perform: removeAlbum) in AddAlbumView()) the new list is passed back to the previews view, but when I'm hitting save the updated list is not saved to the database.

So the workflow is as follows: Select an artist -> Add/Show Albums -> delete an album -> go back -> hit save

The question is: How do I correctly update the list property of my Model (Artist)?

Any help is highly appreciated.

MWE.swift

import SwiftUI

@main
struct MWE_SwiftDataApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }.modelContainer(for: Artist.self)
    }
}

ContentView.swift:

import SwiftUI
import SwiftData

struct ContentView: View {
    var body: some View {
        TabView {
            ArtistView()
                .tabItem {
                    Label("All Items", systemImage: "list.bullet")
                }
            
            ItemView(artist: nil)
                .tabItem {
                    Label("Add", systemImage: "plus")
                }
        }
    }
}

struct ArtistView: View {
    
    @Query private var artists: [Artist]
    @Environment(\.modelContext) private var modelContext
    
    var body: some View {
        NavigationStack {
            List {
                ForEach(artists) { artist in
                    NavigationLink(artist.name) {
                        ItemView(artist: artist)
                    }
                    
                }
            }
            .navigationTitle("Artists")
        }
        
    }
}

struct ItemView: View {
    
    @Environment(\.modelContext) private var modelContext
    
    @State private var name: String = ""
    @State private var albums: [Album] = []
    
    let artist: Artist?
    
    var body: some View {
        NavigationStack {
            Form {
                Section("Name") {
                    TextField("Artist name", text: $name )
                    
                }
                
                Section("Albums"){
                    List {
                        ForEach(albums, id:\.self) { album in
                            Text(album.name)
                        }
                    }
                }

                Section {
                    VStack(alignment: .leading) {
                        NavigationLink("Add/Show Albums", destination: AddAlbumView(artist: name, addedAlbums: $albums))
                        
                    }
                }
                
            
            }
            .onAppear {
                if let artist {
                    name = artist.name
                    
                    if albums.isEmpty {
                        albums = artist.album
                    } else {
                        albums = albums
                    }
                    
                    
                }
            }
            .navigationTitle("New Artist")
            .toolbar {
                ToolbarItem(placement: .navigationBarTrailing) {
                    Button {
                        
                        if let artist {
                            // New list of albums is not applied
                            artist.name = name
                            artist.album = albums
                
                            
                        } else {
                            let newArtist = Artist(name: name, album: albums)
                            modelContext.insert(newArtist)
                            
                            name = ""
                            albums = []
                        }
                     
                        
                        
                    } label: {
                        Text("Save")
                    }
                }
            }
        }
    }
    
}

struct AddAlbumView: View {
    
    var artist: String
    @State private var name: String = ""
    @State private var releaseDate: Date = .now
    
    @Binding var addedAlbums: [Album]
    
    var body: some View {
        NavigationStack {
            VStack(alignment: .leading) {
                
                Text(artist)
                    .font(.headline)
                
                TextField("Album name", text: $name )
                
                DatePicker(selection: $releaseDate, displayedComponents: [.date]) {
                    Label("Release Date", systemImage: "calendar")
                }
                
                Button(action: {
                    
                    let newAlbum = Album(name: name, releaseDate: releaseDate)
                    addedAlbums.append(newAlbum)
                    
                    name = ""
                    
                }, label: {
                    Text("Add")
                        .frame(width: 150, height: 40)
                        .foregroundColor(.white)
                        .background(name.isEmpty ? Color.gray.opacity(1) : Color.blue.opacity(1))
                        .cornerRadius(20)
                        .shadow(radius: 5, y: 8)
                })
                .disabled(name.isEmpty)
                
                Spacer(minLength: 40)
                
                List {
                    ForEach(addedAlbums, id: \.self) { album in
                        HStack {
                            Text(album.name)
                            Spacer()
                            Text("Released: \(album.releaseDate.formatted(date: .abbreviated, time: .omitted))")
                        }
                    }.onDelete(perform: removeAlbum)
                }
                .padding()
                .listStyle(.inset)
            }
            .padding()
            .navigationTitle("Add Album")
        }
    }
    
    func removeAlbum(index: IndexSet) {
        addedAlbums.remove(atOffsets: index)
    }
}

@Model
class Artist {
    @Attribute(.unique) var name: String
    @Relationship(deleteRule: .cascade) var album: [Album]
    
    init(name: String, album: [Album]) {
        self.name = name
        self.album = album
    }
}

@Model
class Album {
    var name: String
    var releaseDate: Date
    
    init(name: String, releaseDate: Date) {
        self.name = name
        self.releaseDate = releaseDate
    }
}
1

1 Answer 1

0

Following the suggest answer I changed the removeAlbum as shown below:

func removeAlbum(index: IndexSet) {
    for i in index {
        let album = addedAlbums[i]
        modelContext.delete(album)
    }
        
    addedAlbums.remove(atOffsets: index)
}

And the issue is solved.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.