有没有办法在初始化后使用谓词修改获取的结果?



我正在尝试为现有的CoreData应用程序(简单的日志记录应用程序(构建搜索视图。 我将所有数据存储在 CoreData 中,并使用@FetchRequest获取:

@State private var searchPredicate: NSPredicate? = NSPredicate(format: "title contains[c] %@", "")
@FetchRequest( entity: Item.entity(), sortDescriptors: [NSSortDescriptor(keyPath: Item.title, ascending: true)],
predicate: NSPredicate(format: "title contains[c] %@", "h")
) 
var items: FetchedResults<Item>

它现在只获取通过谓词测试的项目,在本例中,这些项目都是包含"h"的项目。 然后,我将结果显示在搜索视图正文中的列表中:

List {
ForEach(Items) { Item in
ListViewItem(title: Item.title!, subTitle: Item.subTitle!, createdAt: "(Item.createdAt!)")
}
}

然后,我创建了一个新类"Searchbar",该类在搜索视图中调用,应该根据搜索字段的输入创建一个谓词,然后将其作为绑定传递给父级,然后基于该谓词可以显示正确的项目。

在搜索视图中调用 VStack 顶部的搜索栏:

SearchBar(text: $searchText, predicate: $searchPredicate)

绑定根据用户在"搜索栏"中的输入而变化:

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
text = searchText
predicate = NSPredicate(format: "title contains[c] %@", searchText)
}

目前为止,一切都好。。。

我现在遇到的问题是,我们有一个有效的谓词,但不能在定义中的@Fetchrequest内调用,因为它会在初始化之前被调用。

@State private var searchPredicate: NSPredicate? = NSPredicate(format: "title contains[c] %@", "")

@FetchRequest(
entity: Item.entity(),
sortDescriptors: [
NSSortDescriptor(keyPath: Item.title, ascending: true)
],
predicate: searchPredicate
) var items: FetchedResults<Item>

这给了我一个错误,即在 self 可用之前无法运行属性初始值设定项,这是合乎逻辑的,但让我想知道并让我回到我的问题:有没有办法在初始化后使用谓词修改获取的结果?

我还尝试在 ForEach(( 语句中对获取的结果调用谓词相关方法,但它们似乎都没有奏效。

如果有任何问题,请随时提出。

有没有办法在它们之后使用谓词修改获取的结果 是否初始化?

井。。。不,不是你尝试这样做的方式,即使你尝试使用 NSFetchRequest 实例创建它,它是引用,并允许稍后更改谓词,那也行不通,因为 SwiftUI 的 FetchRequest 存储提供的获取请求的副本(或使用提供的参数创建自己的(......所以,没有。但。。。

您可以拆分提供获取请求参数的视图,以及构造获取请求并显示结果的视图。

下面是方法的演示(其中的重要部分(,它使您可以使用不同的动态更改谓词获得结果:

struct MasterView: View {
@State var predicate: NSPredicate? = nil
var body: some View {
VStack {
Button(action: { // button just for demo
self.predicate = NSPredicate(format: "title contains[c] %@", "h")
}, label: { Text("Filter") })
ResultView(predicate: self.predicate)
}
}
}
struct ResultView: View {
@FetchRequest
var events: FetchedResults<Event>
@Environment(.managedObjectContext)
var viewContext
init(predicate: NSPredicate?) {
let request: NSFetchRequest<Event> = Event.fetchRequest()
request.sortDescriptors = [NSSortDescriptor(keyPath: Event.timestamp, ascending: true)]
if let predicate = predicate {
request.predicate = predicate
}
_events = FetchRequest<Event>(fetchRequest: request)
}

var body: some View {
List {
ForEach(events, id: .self) { event in
...

我决定发布具有Asperi提供的出色答案的完整工作版本,因为我在其他任何地方都没有找到可行的解决方案。

struct MasterView: View {

@State var predicate: NSPredicate? = nil
@State private var searchText = ""

var body: some View {
VStack {

TextField("Search", text: $searchText, onEditingChanged: {_ in

self.predicate = NSPredicate(format: "title contains[c] %@", "(self.searchText)")
print("THE PREDICATE: (String(describing: self.predicate))")

}, onCommit: {
print("onCommit")
}).foregroundColor(.primary)

SearchView(predicate: self.predicate)
}
}

}

和搜索视图:

struct SearchView: View {

@State private var searchText = ""
@Environment(.managedObjectContext) var managedObjectContext

@FetchRequest var items: FetchedResults<Item>

init(predicate: NSPredicate?) {

let request: NSFetchRequest<Item> = Item.fetchRequest() as! NSFetchRequest<Item>
request.sortDescriptors = [NSSortDescriptor(keyPath: Item.title, ascending: true)]
if let predicate = predicate {
request.predicate = predicate
}
_items = FetchRequest<Item>(fetchRequest: request)

}


var body: some View {

VStack {

List {
...

作为对@Asperi回答的内容(Swift 5.4 Xcode 12.5(的一点更新,在 ResultView 中,您现在可以执行此操作:

var fetchRequest: FetchRequest<Event>
init(predicate: NSPredicate?) {
fetchRequest = FetchRequest<Event>(entity: 
Event.entity(), sortDescriptors: [NSSortDescriptor(keyPath: 
Event.timestamp, ascending: true)], predicate: predicate)
}

正如 FetchRequest 在其构造函数中采用 NSPredicate?

public init(entity: NSEntityDescription, sortDescriptors: [NSSortDescriptor], predicate: NSPredicate? = nil, animation: Animation? = nil)

最新更新