M.S*_*rag 6 nsfetchrequest swiftui
我有一个使用@FetchRequest从CoreData中显示对象的列表,我想为用户提供一个条形按钮,单击该按钮将过滤显示的列表。如何更改@FetchRequest谓词并动态地重新运行它,以使用过滤后的项目重建列表?
struct EmployeeListView : View {
@FetchRequest(
entity: Department.entity(),
sortDescriptors: [NSSortDescriptor(keyPath: \Department.name, ascending: false)],
)
var depts: FetchedResults<Department>
@Environment(\.managedObjectContext) var moc
var body: some View {
NavigationView {
List {
ForEach(depts, id: \.self) { dept in
Section(header: Text(dept.name)) {
ForEach(dept.employees, id: \.self) { emp in
Text(emp.name)
}
}
}
}
.navigationBarTitle("Employees")
}
}
}
Run Code Online (Sandbox Code Playgroud)
我知道如何提供过滤器,我不知道如何更改属性包装器谓词并重新运行获取请求。
您可以根据获取谓词中的绑定来更改结果,但对于 Bool vars,我发现这很难做到。原因是,在 CoreData 中测试 Bool 的谓词就像是NSPredicate(format: "myAttrib == YES"),而您的 Bool 绑定变量将是 true 或 false,而不是 YES 或 NO...所以如果您这样做NSPredicate(format: "%K ==%@", #keypath(Entity.seeMe), seeMe.wrappedValue),这将始终为 false。也许我错了,但这就是我的经历。
您可以更轻松地根据字符串数据过滤您的提取。但它的工作方式与下面的示例略有不同,因为您需要在视图的 init() 中运行您的提取,如下所示:
@Binding var searchTerm:String
var fetch: FetchRequest<Entity>
var rows: FetchedResults<Entity>{fetch.wrappedValue}
init(searchTerm:Binding<String>) {
self._searchTerm = searchTerm
self.fetch = FetchRequest(entity: Entity.entity(), sortDescriptors: [], predicate: NSPredicate(format: "%K == %@", #keyPath(Entity.attribute),searchTerm.wrappedValue))
}
Run Code Online (Sandbox Code Playgroud)
要完成您所描述的任务,请单击栏按钮项从而切换 Bool,我建议使用以下示例:
此示例将在不更改 fetch 谓词的情况下实现您的目标。它使用逻辑根据数据模型中的条目和 @State 变量的值来决定是否显示一行数据。
import SwiftUI
import CoreData
import Combine
struct ContentView: View {
@Environment(\.managedObjectContext) var viewContext
@State var seeMe = false
@FetchRequest(
sortDescriptors: [NSSortDescriptor(keyPath: \Entity.attribute, ascending: true)],
animation: .default)
var rows: FetchedResults<Entity>
var body: some View {
NavigationView {
VStack {
ForEach(self.rows, id: \.self) { row in
Group() {
if (self.validate(seeMe: row.seeMe)) {
Text(row.attribute!)
}
}
}
.navigationBarItems(leading:
Button(action: {
self.seeMe.toggle()
}) {
Text("SeeMe")
}
)
Button(action: {
Entity.create(in: self.viewContext, attribute: "See Me item", seeMe: true)
}) {
Text("add seeMe item")
}
Button(action: {
Entity.create(in: self.viewContext, attribute: "Dont See Me item", seeMe: false)
}) {
Text("add NON seeMe item")
}
}
}
}
func validate(seeMe: Bool) -> Bool {
if (self.seeMe && seeMe) {
return true
} else if (!self.seeMe && !seeMe ){
return true
} else {
return false
}
}
}
extension Entity {
static func create(in managedObjectContext: NSManagedObjectContext,
attribute: String,
seeMe: Bool
){
let newEvent = self.init(context: managedObjectContext)
newEvent.attribute = attribute
newEvent.seeMe = seeMe
}
static func save(in managedObjectContext: NSManagedObjectContext) {
do {
try managedObjectContext.save()
} catch {
// Replace this implementation with code to handle the error appropriately.
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
let nserror = error as NSError
fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
}
}
}
Run Code Online (Sandbox Code Playgroud)
要使用此示例,请创建一个核心数据模型,其中包含一个名为“Entity”的实体和两个属性,一个名为“attribute”,为字符串,另一个名为“seeMe”,为 Bool。然后运行它,按按钮创建两种类型的数据,然后单击顶部的栏按钮项选择要显示的数据。
我不是最漂亮的例子,但它应该展示您想要完成的功能。
| 归档时间: |
|
| 查看次数: |
282 次 |
| 最近记录: |