Reputation: 1839
I am using a UISearchController
in my project. I initiate the search controller by supplying the init(searchResultsController)
method with an UIViewController
object that manages a tableView. The code for this object is:
import UIKit
class ResultsTableViewController: UIViewController {
@IBOutlet weak var tableView: UITableView!
var list: [String] = []
override func viewDidLoad() {
super.viewDidLoad()
}
}
extension ResultsTableViewController: UITableViewDelegate{}
extension ResultsTableViewController: UITableViewDataSource{
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return list.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier("Cell")
if cell == nil {
cell = UITableViewCell(style: .Default, reuseIdentifier: "Cell")
cell?.textLabel?.text = list[indexPath.row]
} else {
cell?.textLabel!.text = list[indexPath.row]
}
return cell!
}
}
Furthermore, when I try to access the resultsTableViewController.tableView
from the updateSearchResultsForSearchController(searchController: UISearchController)
method of the UISearchResultsUpdating
protocol to populate its "list" array, it gives me an error. The tableView returns nil and the app crashes. I would like to point out that I have connected the data source, delegate, and the IBOutlet
variable of the tableView to the appropriate view controller. I was hoping for someone to explain to me why this happens? I think I have a misunderstanding in the life cycle of the ResultsTableViewController
. Lastly, when I drag a TableViewController from the storyboard instead of making my own table view controller from scratch everything works smoothly without any errors! Can you please help me understand whats going on here?
Edit: The code for my initial view controller is:
import UIKit
class FirstViewController: UIViewController {
@IBOutlet weak var tableView: UITableView!
var resultsTableViewController = ResultsTableViewController()
var searchController: UISearchController!
let list = ["Apple", "Orange", "Bananas","Kiwi", "Cucumbers", "Apricot","Peach", "Cherry", "Mangosteen","Strawberry", "Blueberry", "Raspberry","Watermelon", "Persimmon", "plums","Papaya", "Jackfruit", "Lichi"]
var filteredList: [String]!
override func viewDidLoad() {
super.viewDidLoad()
setUpSearchController()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func setUpSearchController(){
searchController = UISearchController(searchResultsController: resultsTableViewController)
searchController.dimsBackgroundDuringPresentation = false
searchController.searchResultsUpdater = self
searchController.hidesNavigationBarDuringPresentation = true
tableView.tableHeaderView = searchController.searchBar
tableView.scrollToRowAtIndexPath(NSIndexPath(forRow: 0, inSection: 0), atScrollPosition: UITableViewScrollPosition.Top, animated: false)
}
}
extension FirstViewController: UITableViewDelegate, UITableViewDataSource{
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return list.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier("cell")
if cell == nil {
cell = UITableViewCell(style: .Default, reuseIdentifier: "cell")
cell?.textLabel?.text = list[indexPath.row]
}else {
cell?.textLabel?.text = list[indexPath.row]
}
return cell!
}
}
extension FirstViewController: UISearchResultsUpdating{
func updateSearchResultsForSearchController(searchController: UISearchController) {
filteredList = list.filter({
item in
return item.containsString(searchController.searchBar.text!)
})
resultsTableViewController.list = filteredList
resultsTableViewController.tableView.reloadData()
}
}
Upvotes: 3
Views: 1833
Reputation: 114866
var resultsTableViewController = ResultsTableViewController()
creates a new ResultsTableViewController
but it isn't linked to your storyboard scene, so none of the @IBOutlet
s will be set. You need to set an identifier for your scene (say resultsViewController) and then use that to instantiate the view controller from the storyboard:
var resultsTableViewController: ResultsTableViewController!
override func viewDidLoad() {
super.viewDidLoad()
setUpSearchController()
}
func setUpSearchController(){
let storyboard = UIStoryboard(name: "MyStoryboardName", bundle: nil)
self.resultsTableViewController = storyboard.instantiateViewControllerWithIdentifer("resultsViewController") as! ResultsTableViewController
searchController = UISearchController(searchResultsController: resultsTableViewController)
searchController.dimsBackgroundDuringPresentation = false
searchController.searchResultsUpdater = self
searchController.hidesNavigationBarDuringPresentation = true
tableView.tableHeaderView = searchController.searchBar
tableView.scrollToRowAtIndexPath(NSIndexPath(forRow: 0, inSection: 0), atScrollPosition: UITableViewScrollPosition.Top, animated: false)
}
Upvotes: 4