SwiftUI:使用 Picker(分段)更改 ForEach 源或获取请求
Posted
技术标签:
【中文标题】SwiftUI:使用 Picker(分段)更改 ForEach 源或获取请求【英文标题】:SwiftUI: Change ForEach source or fetch request using Picker (Segmented) 【发布时间】:2020-09-02 21:42:28 【问题描述】:我是 SwiftUI 和一般编码的新手,如果之前已经介绍过,非常抱歉。我确实搜索过它,但我找不到它足够清楚。
我正在尝试制作一个用于存储笔记和任务的应用程序。 (我不打算把它放在商店里,我太新手了,但我确实想学习 Swift 并且开发一个实际的应用程序对我来说比阅读它更有用。)我有一个名为的实体“基础”具有 8 个属性和选择的自动 Codegen 类定义。我更喜欢保持这种方式,请不要使用手册。
我有三个获取请求。一个从 Core Data 获取所有数据。另外两个过滤一个名为 campoEstado 的属性。目前在 campoEstado 中,我只存储两个可能值之一,作为字符串:“Activas”和“Pospuestas”。将来我可能会添加更多内容,因此我不能为此使用布尔值。
我得到一个处理一个获取请求的列表。但是当应用程序运行时,我无法更改该来源。 我用 .pickerStyle(SegmentedPickerStyle()) 制作了一个选择器,它向我展示了:Todo、Activas、Pospuestas。当用户在选择器中选择此选项卡之一时,列表应更改为:
标签 1:所有任务 选项卡 2:过滤后的列表仅包含 campoEstado = "Activas" 的任务(调用获取请求 filtroActivas) 选项卡 3:过滤列表仅包含 campoEstado = "Pospuestas" 的任务(调用获取请求 filtroPospuestas)它应该是什么样子:
我在 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")
我有两个问题:
我不知道如何将选择器中选定的选项卡与 List 中的 ForEach 的源连接起来
我使列表适用于一个获取请求,该请求为我带来了 Core Data 中的每条记录,但我不知道如何在应用程序运行时更改 ForEach 源。我已经为每个获取请求变量名称(bases、filtroActivas 和 filtroPospuestas)尝试了一组变量名称,将它们放在 [] 中,但没有奏效。
我知道这并不优雅,我只需要它先工作,然后再追求效率和优雅。我确定有一些愚蠢的事情我没有看到,但已经一个星期了,我越来越绝望了。
我希望我很清楚,如果您需要更多信息,请询问。 如果有人可以帮助我,我将不胜感激。提前致谢!
【问题讨论】:
【参考方案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
【讨论】:
非常感谢,我会看看如何使它与 CoreData 一起工作。我喜欢 SwiftUI,所以我在努力耐心学习它,否则我会在一周内感到沮丧。 顺便说一句,我想说我非常感谢您为回答所付出的努力。编码很好地分离和注释。再次感谢。 所以我试了一下,我得到了一些错误。首先,我使用 NavigationView 而不是 VStack。在` .onAppear(perform: self.loadFetchedResults() ) `我得到这个错误:“'ContentView'类型的值没有成员'loadFetchedResults'” 然后,在函数 func loadFetchedResults() 中,每行都会出现如下错误:“使用未解析的标识符 'fetchedResultsBases'” 第一个错误意味着它没有看到“loadFetchedResults”函数。确保您在 ContentView 结构中拥有该功能,而不是在它之外。仔细查看打开和关闭的花括号 第二个错误意味着没有名为“fetchedResultsBases”的常量。这可能与第一个错误有关,或者可能在您的代码中拼写错误。我编辑了代码以包含一个可能有用的 NavigationView。以上是关于SwiftUI:使用 Picker(分段)更改 ForEach 源或获取请求的主要内容,如果未能解决你的问题,请参考以下文章
每次渲染正文时都会调用 SwiftUI Picker onReceive()
SwiftUI Segmented Picker 在点击时不会切换
如何在 SwiftUI 中使用多个 Picker 更改 UIPickerView 宽度?