Для приложения книжного клуба я пишу В SwiftUI
у меня есть NavigationSplitView
, в ведущем столбце которого есть выбираемый List
. Первый элемент в списке — «Книга», и если он выбран, он приведет пользователя к PDF-файлу книги. Ниже находится значок Button
со значком плюса, который позволяет пользователю добавить читателя книги. Как только читатель будет добавлен, его имя появится на List
чуть ниже плюса Button
. Если пользователь выберет читателя, он будет перенаправлен на страницу своего профиля.
Цель всего этого состоит в том, чтобы «Книга» и список читателей были объединены в один элемент выбора List
, так что при выборе одного элемента он подсвечивается, а предыдущий выбранный элемент теряет свою подсветку.
Это код:
import SwiftUI
import SwiftData
enum ListItem: Hashable
{
case book
case reader(Reader)
}
struct ProjectView: View
{
private let project: Project
@Environment(\.modelContext) private var modelContext
@Query private var readers: [Reader]
@State private var alertPresented = false
@State private var userInput = ""
@State private var selectedListItem: ListItem?
init(project: Project)
{
self.project = project
}
var body: some View
{
NavigationSplitView
{
List(selection: self.$selectedListItem)
{
Text("Book").tag(ListItem.book)
Divider()
Button(action:
{
self.alertPresented = true
},
label:
{
Label("", systemImage: "plus")
})
.buttonStyle(PlainButtonStyle())
.alert("Reader Name:", isPresented: self.$alertPresented)
{
TextField("", text: self.$userInput)
Button("OK")
{
let reader = Reader(name: self.userInput)
self.modelContext.insert(reader)
self.project.readers?.append(reader)
self.selectedListItem = ListItem.reader(reader)
self.userInput = ""
}
.keyboardShortcut(.defaultAction)
Button("Cancel", role: .cancel) { }
}
ForEach (self.readers , id: \.self)
{
reader in Text(reader.name).tag(ListItem.reader(reader))
}
}
.onAppear
{
self.selectedListItem = ListItem.book
}
}
detail:
{
Text("Detail")
}
}
}
Все работало нормально, пока я не добавил CloudKit
в свой проект. Теперь иногда, когда я добавляю читателя, я получаю сообщение:
Неустранимая ошибка: в Словарь. Обычно это означает, что тип нарушает Требования Hashable или этот член такого словаря были мутировал после вставки.
Кроме того, это List
не будет работать с CloudKit
и обновлять любые добавленные программы чтения на других устройствах (когда другие экраны нормально работают с CloudKit). Когда я полностью удаляю enum ListItem
и пункт «Книга» вверху и просто отображаю список читателей, используя self.readers
и self.selectedReader
вместо self.selectedListItem
, то все работает нормально. Итак, я считаю, что проблема заключается в использовании перечисления и объединении элемента «Книга» и списка читателей в один, но я не понимаю, почему. Любая помощь будет оценена по достоинству! Для справки ниже приведены мои классы моделей Project
и Reader
:
import Foundation
import SwiftData
@Model
class Project
{
var name: String = ""
@Relationship(deleteRule: .cascade, inverse: \Reader.projects) var readers : [Reader]?
init(name: String)
{
self.name = name
self.readers = []
}
}
import Foundation
import SwiftData
@Model
class Reader
{
var name: String = ""
var projects: [Project]?
init(name: String)
{
self.name = name
}
}
@workingdogsupportUkraine Спасибо, я поменяю ForEach (всегда забываю об этом). Я знаю, что self не является обязательным, но мне нравится его использовать, потому что это помогает мне различать другие переменные.
Вы случайно реализовали собственное соответствие Hashable, Equatable или Identifying for Reader?
@JoakimDanielson Нет. Фактически исправлена проблема с советом первого комментатора и изменением ForEach(self.readers, id: \.self) на ForEach(readers).
@workingdogsupportUkraine Изменение ForEach(self.readers, id: \.self) на ForEach(readers) фактически устранило проблему!
Удалось решить проблему с помощью рабочей поддержки Украины, предложив поменять ForEach(self.readers , id: \.self)
на ForEach(readers)
.
Обратите внимание:
self.
больше не нужен, и поскольку@Model
соответствуетIdentifiable
, вам следует использоватьForEach(readers)
, а неForEach(self.readers , id: \.self)
.