我正在尝试在顶部的搜索栏上创建一个People
的简单列表视图。
我放下了UI,但是编辑搜索栏并没有调用didSet
的{{1}}函数。
我相信我可能误解了@State var searchText: String
和@State
的工作方式?好像将Binding
绑定到viewModel.$searchText
永远不会导致SearchBar
更新。
怎么了?
@State var searchText
答案 0 :(得分:0)
没关系,我想出了自己的问题。我需要@Published
,而不是@State
,并且$
放在错误的位置。工作代码:
struct ListView: View {
@Environment(\.managedObjectContext) var context: NSManagedObjectContext
@ObservedObject var viewModel: PeopleListViewModel
var body: some View {
VStack {
SearchBar(text: $viewModel.searchText, showsCancelButton: .constant(false))
.padding(Edge.Set(arrayLiteral: .top, .bottom), 0)
.padding(Edge.Set(arrayLiteral: .leading, .trailing), 8)
List(viewModel.people, id: \.id) { (person) in
PersonCell(person: person)
}
}
}
}
extension ListView {
final class PeopleListViewModel: NSObject, NSFetchedResultsControllerDelegate, ObservableObject {
private let peopleController: NSFetchedResultsController<Person>
private let sortDescriptors = [NSSortDescriptor(keyPath: \Person.name, ascending: true)]
@Published var searchText: String = "" {
didSet {
if oldValue != searchText {
updatePeople()
}
}
}
init(managedObjectContext: NSManagedObjectContext) {
peopleController = Person.resultsController(context: managedObjectContext, sortDescriptors: sortDescriptors)
super.init()
peopleController.delegate = self
try? peopleController.performFetch()
}
func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
objectWillChange.send()
}
var people: [Person] {
return peopleController.fetchedObjects ?? []
}
func updatePeople() {
var predicate: NSPredicate?
if !searchText.isEmpty {
predicate = NSPredicate(format: "name CONTAINS[cd] %@", argumentArray: [searchText])
}
peopleController.fetchRequest.predicate = predicate
try? peopleController.performFetch()
}
}
}
extension Person {
static func resultsController(context: NSManagedObjectContext, sortDescriptors: [NSSortDescriptor] = []) -> NSFetchedResultsController<Person> {
let request = NSFetchRequest<Person>(entityName: "Person")
request.sortDescriptors = sortDescriptors.isEmpty ? nil : sortDescriptors
return NSFetchedResultsController(fetchRequest: request, managedObjectContext: context, sectionNameKeyPath: nil, cacheName: nil)
}
}