我正在使用Core Data创建一个TableViewController。实际上,用户可以向表视图添加新项目,这些项目将保存在核心数据中。视图将显示联系人列表。 一切都运行良好,但我找不到搜索栏工作。我尝试了很多,但我是swift的新手,这是我的第一个应用程序。请告诉我应该在代码中添加什么内容?
class ContactsViewController: UITableViewController {
@IBOutlet var searchBar: UISearchBar!
var contacts: [NSManagedObject] = []
override func viewDidLoad() {
super.viewDidLoad()
fetch()
tableView.reloadData()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//MARK: - Data Source
func fetch() {
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
let managedObjectContext = appDelegate.persistentContainer.viewContext
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName:"Contact")
do {
contacts = try managedObjectContext.fetch(fetchRequest) as! [NSManagedObject]
} catch let error as NSError {
print("Could not fetch. \(error)")
}
}
func save(name: String, phoneNumber: String, dataUltimei: String) {
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
let managedObjectContext = appDelegate.persistentContainer.viewContext
guard let entity = NSEntityDescription.entity(forEntityName:"Contact", in: managedObjectContext) else { return }
let contact = NSManagedObject(entity: entity, insertInto: managedObjectContext)
contact.setValue(name, forKey: "name")
contact.setValue(phoneNumber, forKey: "phoneNumber")
contact.setValue(dataUltimei, forKey: "dataUltimei")
do {
try managedObjectContext.save()
self.contacts.append(contact)
} catch let error as NSError {
print("Couldn't save. \(error)")
}
}
func update(indexPath: IndexPath, name:String, phoneNumber: String, dataUltimei: String) {
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
let managedObjectContext = appDelegate.persistentContainer.viewContext
let contact = contacts[indexPath.row]
contact.setValue(name, forKey:"name")
contact.setValue(phoneNumber, forKey: "phoneNumber")
contact.setValue(dataUltimei, forKey: "dataUltimei")
do {
try managedObjectContext.save()
contacts[indexPath.row] = contact
} catch let error as NSError {
print("Couldn't update. \(error)")
}
}
func delete(_ contact: NSManagedObject, at indexPath: IndexPath) {
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
let managedObjectContext = appDelegate.persistentContainer.viewContext
managedObjectContext.delete(contact)
contacts.remove(at: indexPath.row)
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return contacts.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ContactCell", for: indexPath)
var contact = contacts[indexPath.row]
if isSearching {
contact = contacts[indexPath.row]
}
else {
contact = contacts[indexPath.row]
}
cell.textLabel?.text = contact.value(forKey:"name") as? String
}
return cell
}
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
do {
let contact = contacts[indexPath.row]
delete(contact, at: indexPath)
fetch()
tableView.reloadData()
} catch let error as NSError {
print("Could not save. \(error), \(error.userInfo)")
}
}
}
override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
// Return false if you do not want the specified item to be editable.
return true
}
@IBAction func unwindToContactList(segue: UIStoryboardSegue) {
if let viewController = segue.source as? AddContactViewController {
guard let name: String = viewController.nameTextField.text, let phoneNumber: String = viewController.phoneNumberTextField.text, let dataUltimei: String = viewController.tabel.text else { return }
if name != "" && phoneNumber != "" {
if let indexPath = viewController.indexPathForContact {
update(indexPath: indexPath, name: name, phoneNumber: phoneNumber, dataUltimei: dataUltimei)
} else {
save(name:name, phoneNumber:phoneNumber, dataUltimei:dataUltimei)
}
}
tableView.reloadData()
} else if let viewController = segue.source as? ContactDetailViewController {
if viewController.isDeleted {
guard let indexPath: IndexPath = viewController.indexPath else { return }
let contact = contacts[indexPath.row]
delete(contact, at: indexPath)
tableView.reloadData()
}
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "contactDetailSegue" {
guard let navViewController = segue.destination as? UINavigationController else { return }
guard let viewController = navViewController.topViewController as? ContactDetailViewController else { return }
guard let indexPath = tableView.indexPathForSelectedRow else { return }
let contact = contacts[indexPath.row]
viewController.contact = contact
viewController.indexPath = indexPath
}
}
}
答案 0 :(得分:1)
添加以下功能:
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
if !searchText.isEmpty {
var predicate: NSPredicate = NSPredicate()
predicate = NSPredicate(format: "name contains[c] '\(searchText)'")
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
let managedObjectContext = appDelegate.persistentContainer.viewContext
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName:"Contact")
fetchRequest.predicate = predicate
do {
contacts = try managedObjectContext.fetch(fetchRequest) as! [NSManagedObject]
} catch let error as NSError {
print("Could not fetch. \(error)")
}
}
tableView.reloadData()
}
添加UISearchBarDelegate和UISearchDisplayDelegate,如下所示:
class ViewController: UIViewController, UISearchBarDelegate, UISearchDisplayDelegate
在viewDidLoad中添加searchBar委托:
searchBar.delegate=self
答案 1 :(得分:1)
要添加到@ViniApp的出色答案
在当今的Swift中,您可能会遇到类似的情况
var searchLetters: String = "" {
didSet {
runCoreDataFetchRequest()
reloadData()
}
}
因此,只要更改,
override var theFetchRequest: NSFetchRequest<NSFetchRequestResult> {
let r = NSFetchRequest<NSFetchRequestResult>(entityName: relevantEntityName)
let s = NSSortDescriptor(key: "id", ascending: false) // for example
r.sortDescriptors = [s]
if searchLetters != "" {
let p = NSPredicate(format: "firstname contains[c] %@", searchLetters)
r.predicate = p
}
return r
}
请注意,以上示例中的“名字”实际上只是您要搜索的实际Core Data实体中的实际字段的名称,因此显然使用实际项目中的实际字段名称,而不是“ firstname” “。
请注意,获取请求是使用searchLetters
然后,您的核心数据调用的核心将是:
var frc: NSFetchedResultsController<NSFetchRequestResult>!
func runCoreDataFetchRequest() {
frc = NSFetchedResultsController(
fetchRequest: theFetchRequest,
managedObjectContext: core.container.viewContext,
sectionNameKeyPath: nil,
cacheName: nil)
frc.delegate = self
do {
try frc.performFetch()
} catch {
fatalError("frc fetch fail \(error)")
}
}
请注意,无论当前值是多少,它都会使用theFetchRequest
。
因此,简而言之,runCoreDataFetchRequest为您运行performFetch
。
最后不要忘记,在运行获取后,您只需重新加载表或集合视图:
请注意
var searchLetters: String = "" {
didSet {
runCoreDataFetchRequest()
reloadData()
}
}
设置searchLetters
实际上可以完成整个工作!