SwiftUI: изменение источника ForEach или запроса выборки с помощью средства выбора (сегментировано)
Я новичок в SwiftUI и кодировании в целом, извините, если об этом уже говорилось раньше. Я искал об этом, но не смог найти достаточно ясного.
Пытаюсь сделать приложение для хранения заметок и задач. (Я не планирую выкладывать его в магазин, я слишком новичок для этого, но я действительно хочу изучить Swift, и работа над реальным приложением для меня более полезна, чем чтение об этом.) У меня есть объект под названием "Базовый" с 8 атрибутами и выбранным автоматическим определением класса Codegen. Я предпочитаю оставить это так, пожалуйста, без руководства.
У меня три запроса на выборку. Я получаю все данные из Core Data. Два других фильтруют один атрибут, называемый campoEstado. На данный момент в campoEstado я храню только одно из двух возможных значений в виде строк: "Activas" и "Pospuestas". В будущем я могу добавить больше, поэтому я не могу использовать для этого логическое значение.
Я получаю список, работающий с одним запросом на выборку. Но я не могу изменить этот источник, когда приложение работает. Я сделал Picker с.pickerStyle(SegmentedPickerStyle()), который показывает мне: Todo, Activas, Pospuestas. Когда пользователь выбирает одну из этих вкладок в средстве выбора, список должен измениться на:
- Вкладка 1: Все задачи
- Вкладка 2: отфильтрованный список, содержащий только задачи с campoEstado = "Activas" (вызывает запрос на выборку filterroActivas)
- Вкладка 3: отфильтрованный список, содержащий только задачи с campoEstado = "Pospuestas" (вызывает запрос на выборку filterroPospuestas)
Как это должно выглядеть:
Мой код в ContentView:
struct ContentView: View {
@Environment(\.managedObjectContext) var moc
@FetchRequest(entity: Base.entity(), sortDescriptors: [
NSSortDescriptor(keyPath: \Base.campoNota, ascending: true),
NSSortDescriptor(keyPath: \Base.campoFechaCreacion, ascending: true)
], predicate: NSPredicate(format: "campoEstado == %@", "Activas")
) var filtroActivas: FetchedResults<Base>
@FetchRequest(entity: Base.entity(), sortDescriptors: [
NSSortDescriptor(keyPath: \Base.campoNota, ascending: true),
NSSortDescriptor(keyPath: \Base.campoFechaCreacion, ascending: true)
], predicate: NSPredicate(format: "campoEstado == %@", "Pospuestas")
) var filtroPospuestas: FetchedResults<Base>
@FetchRequest(entity: Base.entity(), sortDescriptors: [
NSSortDescriptor(keyPath: \Base.campoNota, ascending: true),
NSSortDescriptor(keyPath: \Base.campoFechaCreacion, ascending: true)
]
) var bases: FetchedResults<Base>
var body: some View {
NavigationView {
List {
Picker("Solapas", selection: $selectorIndex) {
//This should connect to ForEach source, currently "bases"
}
.pickerStyle(SegmentedPickerStyle())
ForEach(bases, id: \.self) { lista in
NavigationLink(destination: VistaEditar(base: lista)) {
Rectangle()
.foregroundColor(.gray)
.frame(width: 7, height: 50)
VStack(alignment: .leading) {
Text(lista.campoNota ?? "Unknown title")
.font(.headline)
Text(lista.campoEstado ?? "Activas")
}
}
}
У меня две проблемы:
Я не знаю, как связать выбранную вкладку в средстве выбора с источником ForEach внутри списка
Я заставил список работать для одного запроса на выборку, который приносит мне все записи в Core Data, но я не знаю, как изменить источник ForEach, когда приложение работает. Я пробовал использовать массив имен переменных для каждого из имен переменных запросов на выборку (баз, фильтроактивас и фильтропоспуэстас), помещая их в [], но это не сработало.
Я знаю, что это не изящно, мне просто нужно, чтобы сначала работало, а потом уже работало эффективность и элегантность. Я уверен, что есть какая-то глупость, которую я не вижу, но прошла неделя, и я в отчаянии.
Надеюсь, я был понятен, если вам нужна дополнительная информация, спросите. Если кто-нибудь может мне помочь, я был бы очень признателен. Заранее спасибо!
1 ответ
Я боюсь, что меня могут проголосовать против, потому что это не совсем полный ответ. Но у меня нет времени, и я хотел посмотреть, смогу ли я направить вас в правильном направлении.
Я считаю, что вы ищете массив массивов. АFetchedResult
вернет необязательный массив, который вам нужно убедиться, что он не равен нулю. я использовалcompactMap
в моем примере для генерации ненулевого массива из моих образцов дополнительных массивов, которые предназначены для имитации того, что вы получаете от своего @FetchRequest
свойства. Вы должны иметь возможность загрузить этот код в новый проект в Xcode, чтобы увидеть результаты. Опять же, это не полный ответ, но, надеюсь, он поможет вам в вашем проекте. Надеюсь, это поможет, продолжайте работать над этим, вы получите это!
struct ContentView: View {
// Sample data to mimic optional FetchedResults coming from CoreData.
// These are your @FetchRequest properties
let fetchedResultsBases: [String?] = ["Red", "Green", "Blue"]
let fetchedResultsFiltroPospuestas: [String?] = ["1", "2", "3"]
let fetchedResultsFiltroActivas: [String?] = ["☺️", "", ""]
// Options for your picker
let types = ["Bases", "Pospuestas", "Activas"]
@State private var groups = [[String]]()
@State private var selection = 0
var body: some View {
NavigationView {
VStack {
Picker("Solapas", selection: $selection) {
ForEach(0..<types.count, id: \.self) {
Text("\(self.types[$0])")
}
}.pickerStyle(SegmentedPickerStyle())
List {
ForEach(0..<groups.count, id: \.self) { group in
Text("\(self.groups[self.selection][group])")
}
}
}
}
.onAppear(perform: {
self.loadFetchedResults()
})
} // This is the end of the View body
func loadFetchedResults() {
// This is where you'll create your array of fetchedResults, then add it to the @State property.
var fetchedResults = [[String]]()
// Use compact map to remove any nil values.
let bases = fetchedResultsBases.compactMap { $0 }
let pospuestas = fetchedResultsFiltroPospuestas.compactMap { $0 }
let filtroActivas = fetchedResultsFiltroActivas.compactMap { $0 }
fetchedResults.append(bases)
fetchedResults.append(pospuestas)
fetchedResults.append(filtroActivas)
groups = fetchedResults
}
} // This is the end of the ContentView struct