SwiftData 更新模型的列表属性

问题描述 投票:0回答:1

我有以下问题,请参考下面的代码。 在应用程序中,我可以创建一个艺术家 (

@Model
) 并向其添加一些专辑 (
@Model
)。这些按预期存储和显示。

当我再次启动应用程序并导航到艺术家以删除例如专辑时(使用

.onDelete(perform: removeAlbum)
中的
AddAlbumView()
),新列表将传回预览视图,但是当我点击
save
时更新后的列表不会保存到数据库中。

所以工作流程如下: 选择艺术家 ->

Add/Show Albums
-> 删除专辑 -> 返回 -> 点击
save

问题是:如何正确更新我的模型(艺术家)的列表属性?

非常感谢任何帮助。

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
    }
}
swift swiftui crud mobile-development swiftdata
1个回答
0
投票

按照建议答案,我更改了

removeAlbum
,如下所示:

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

问题就解决了。

© www.soinside.com 2019 - 2024. All rights reserved.