Reputation: 1085
Now I have UISearchBar
(I don't add UISearchDisplayController).
Now I need: When I type some words inside UISearchBar
and press enter, the CategoryListViewController
should show the searching results. If I don't input anything inside the search bar, the CategoryListViewController
should show all data.
After typed words and click enter button, I can get the text I input. But how to show the searching results? (I use core data to store data).
About the CategoryListViewController
:
import Foundation
import UIKit
import CoreData
class CategoryListViewController: UIViewController,UITableViewDataSource, UITableViewDelegate,UISearchBarDelegate
{
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
guard let count = resultController?.sections?.count else
{
return 0
}
return count
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
if (searchCategory != nil)
{
return 1
}
guard let count = resultController?.sections?[section].numberOfObjects
else
{
return 0
}
return count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell:UITableViewCell
cell = tableView.dequeueReusableCellWithIdentifier("firstrow", forIndexPath: indexPath)
if let category = resultController?.objectAtIndexPath(indexPath) as? Category, let title = category.title,let images = category.image
{
cell.textLabel?.text = title
let number = images.count
cell.detailTextLabel?.text = "Contains \(number) images"
}
return cell
}
@IBOutlet weak var tableView: UITableView!
@IBOutlet weak var searchView: UISearchBar!
func searchBarCancelButtonClicked(searchBar: UISearchBar)
{
self.view.endEditing(true)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
{
switch segue.identifier {
case .Some("catSegue"):
let indexPath = tableView.indexPathForSelectedRow!
let viewController = segue.destinationViewController as! CatImagesViewController
viewController.navigationItem.title = "Cat Images"
tableView.deselectRowAtIndexPath(indexPath, animated: false)
if let category = resultController?.objectAtIndexPath(indexPath) as? Category, /*let title = category.title,*/ let images = category.image
{
viewController.target_category = category
viewController.number_of_cells = images.count
}
default:
super.prepareForSegue(segue, sender: sender)
}
}
// MARK: View Life Cycle
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
searchView.delegate = self
//--------------------------------
if (searchCategory != nil)
{
resultController = try? CatService.sharedCatService.catCategories(searchCategory)
}
else
{
resultController = try? CatService.sharedCatService.catCategories()
}
}
func searchBarSearchButtonClicked(searchBar: UISearchBar) {
// print("searchText2 \(searchBar.text)")
searchCategory = searchBar.text
self.viewDidLoad()
}
private var searchCategory:String?
private var resultController: NSFetchedResultsController?
private var imageController: NSFetchedResultsController?
}
About the core data part to get the searching results:
func catCategories(searchTerm: String? = nil) throws -> NSFetchedResultsController {
let fetchRequest = NSFetchRequest(entityName: "Category")
//let fetchRequest = NSFetchRequest(namedEntity: Image.self)
if let someSearchTerm = searchTerm
{
fetchRequest.predicate = NSPredicate(format: "title == %@", someSearchTerm )
print("somesearchTerm is \(someSearchTerm)")
}
fetchRequest.sortDescriptors = [NSSortDescriptor(key:"title",ascending: true)]
let mainQueueContext = CoreDataService.sharedCoreDataService.mainQueueContext
let fetchResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: mainQueueContext, sectionNameKeyPath: nil, cacheName: nil)
try fetchResultsController.performFetch()
return fetchResultsController
}
Upvotes: 0
Views: 1133
Reputation: 80265
I also like to filter "in place", i.e. without using a search controller and an overlay with search results. I usually follow this pattern.
You should set the predicate of the fetched results controller's fetch request to nil
explicitly if the search term is nil
or has no content.
fetchRequest.predicate = (someSearchTerm ?? "").characters.count == 0 ? nil :
NSPredicate(format:"title BEGINSWITH %@", someSearchTerm!)
Second, you need to implement this UISearchBarDelegate
method
func searchBarSearchButtonClicked(searchBar: UISearchBar) {
searchBar.resignFirstResponder()
someSearchTerm = searchBar.text
fetchedResultsController.performFetch()
tableView.reloadData()
}
Upvotes: 1