fja
fja

Reputation: 1839

Why is my tableView variable returning nil?

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

Answers (1)

Paulw11
Paulw11

Reputation: 114866

var resultsTableViewController = ResultsTableViewController()

creates a new ResultsTableViewController but it isn't linked to your storyboard scene, so none of the @IBOutlets 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

Related Questions