我有以下问题,请参考下面的代码。 在应用程序中,我可以创建一个艺术家 (
@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
}
}
按照建议答案,我更改了
removeAlbum
,如下所示:
func removeAlbum(index: IndexSet) {
for i in index {
let album = addedAlbums[i]
modelContext.delete(album)
}
addedAlbums.remove(atOffsets: index)
}
问题就解决了。