У меня есть приложение, которое хранит данные о транзакциях с классификацией категорий. Имена категорий могут быть выбраны из пула вложенных имен или добавлены посредством ввода текста. Проблема, с которой я сталкиваюсь, связана с выбором категорий из пула имен.
Структура GetCategory предназначена для выбора категории транзакции. Например, покупка некоторых товаров в продуктовом магазине может быть отнесена к категории продуктов питания. Возвращаемое значение этой структуры — вернуть строку имени категории.
При выборе категории появляется предупреждающее сообщение:
Процесс выбора категории транзакции выдает ошибку Picker: выбор «nil» недействителен и не имеет связанного тега, это даст неопределенные результаты.
Я пробовал процесс выбора с тегом и без него, а также с необязательным параметром и без него, но, похоже, не приближаюсь к устранению этого предупреждения и ошибки.
При выборе флага используемой категории catInuse устанавливается значение true.
struct GetCategory: View {
@EnvironmentObject var categories: Categories
@Binding var entryCat: CatModel?
var categoryList: [CatModel] {
return categories.catItem.filter(\.catInUse)
}
var body: some View {
ForEach(categoryList) { list in
Text(list.catName)
}
Section(header: Text("Select Category")) {
Picker("", selection: $entryCat) {
ForEach(categoryList) { category in
Text(category.catName)
.tag(Optional(category.id))
}
}.pickerStyle(MenuPickerStyle())
}
if let gotName = entryCat {
Text("Selected Category is \(gotName.catName)")
.padding(.top, 15)
}
}
}
Каждый элемент Picker должен иметь связанный тег. Если вы хотите состояние «Ничего не выбрано», вам нужно добавить пункт меню для Nothing selected, который также может отображать пустую строку. Если нет, вы должны назначить элемент по умолчанию свойству entryCat.
Мне не нужен ничего не выбранный пункт меню
Привет @workingDog: Спасибо за помощь. GetCategory() прекрасно работает, поскольку вы создали его без каких-либо предупреждений, но если я добавлю строку if category.catInUse вокруг текстовой строки, я получаю предупреждение консоли «Выборщик: выбор «CatModel (catNum:, catName: «жилье», catTotal: , catBudget:, catPix:, catInUse: false, catCustom:)" недействителен и не имеет связанного тега, это даст неопределенные результаты». Категория «Проживание» — первая из 14 доступных категорий для использования в приложении, но в данном случае пользователь не выбрал категорию «Проживание».
Мне не нужен ничего не выбранный пункт меню. Средство выбора должно отображать что-то, если ничего не выбрано, по крайней мере, пустую строку, которая технически является пустым пунктом меню. Альтернативой, как я уже сказал, является назначение значения по умолчанию или скрытие средства выбора. Таким образом, в отличие от selection свойства List, свойство entryCat должно быть необязательным.
Привет @vadian. Приложение разработано таким образом, что если из пула имен категорий не выбрано ни одной категории, появится сообщение, указывающее, что категории необходимо выбрать, и запрещающее ввод транзакции. После выбора группы рабочих категорий эта группа появится при вводе транзакции в выпадающем списке. Предупреждение, которое я вижу в консоли, возникает, когда первая категория в большом пуле не выбрана и не отображается среди рабочих категорий.
Поразмыслив, вот еще один подход, который использует entryCat: CatModel? и проверяет его не nil перед отображением Picker. Таким образом, опция выбора nil невозможно.
Приведенный ниже код — это всего лишь пример кода, который у меня работает, т. е. он не выдает предупреждений. Вам необходимо отрегулировать код в соответствии с вашими потребностями.
struct CatModel: Codable, Identifiable, Hashable {
var id = UUID()
var catNum: Int // used by setup categories
var catName: String // category name
var catTotal: Double // category total
var catBudget: Double // category budget
var catPix: String // sf symbol
var catInUse: Bool // catInUse: true = category in use
var catCustom: Bool // true = custom category (can be deleted)
}
struct ContentView: View {
@StateObject var categories = Categories()
@State var entryCat: CatModel? // <-- here
var body: some View {
VStack (spacing: 55) {
Text("Selected is \(entryCat?.catName ?? "no selection")") // <-- here for testing
GetCategory(entryCat: $entryCat)
.environmentObject(categories)
// for testing, change some catInUse to true
Button("click to test") {
// change the first false catInUse to true
if let first = categories.catItem.firstIndex(where: {!$0.catInUse}) {
categories.catItem[first].catInUse = true
entryCat = categories.catItem[first]
}
}
}
}
}
class Categories: ObservableObject {
// this is for testing purpose
@Published var catItem = [
CatModel(catNum: 0, catName: "Cat A", catTotal: 0.0, catBudget: 0, catPix: "a.circle", catInUse: false, catCustom: true),
CatModel(catNum: 1, catName: "Cat B", catTotal: 0.0, catBudget: 0, catPix: "b.circle", catInUse: true, catCustom: true),
CatModel(catNum: 2, catName: "Cat C", catTotal: 0.0, catBudget: 0, catPix: "c.circle", catInUse: true, catCustom: true)
//..... more CatModel
]
//..... more code
}
struct GetCategory: View {
@EnvironmentObject var categories: Categories
@Binding var entryCat: CatModel? // <-- here
var categoryList: [CatModel] {
categories.catItem.filter(\.catInUse)
}
var body: some View {
VStack {
Section(header: Text("Select Category")) {
if entryCat != nil { // <-- here
Picker("", selection: $entryCat) {
ForEach(categoryList) { category in
Text(category.catName).tag(category as CatModel?) // <-- here, needed
}
}.pickerStyle(MenuPickerStyle())
} else {
Text("No selections available").foregroundColor(.red) // <-- here is entryCat == nil
}
}
}
.onAppear {
// <-- try to make entryCat not nil, for testing if needed
if entryCat == nil {
if let theEntryCat = categoryList.first {
entryCat = theEntryCat
}
}
}
}
}
Я не понимаю, что вы делаете с категориями класса. Каждая запись имеет значения catName, catTotal, catBudget, catPix, catInUse и catCustom. Я должен добавить все это к издателю? В ContentView @State entryCat показывает ошибку «Отсутствуют аргументы для параметров catTotal, catBudget и т. д. Разница между вашим кодом и моим заключается в классе.
Обновил мой ответ другим подходом, который использует CatModel?. Дайте мне знать, если это то, что вы ищете.
Отвечает ли это на ваш вопрос? Выбор средства выбора "0" недействителен и не имеет связанного тега