1

I have created a standard iOS project in Xcode 6 beta 6 and added a Search Bar and Search Display Controller to the Main.Storyboard. I also added in a couple of delegate functions for searchDisplayController which appear to work, however when it comes to searching the following error pops up:

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'unable to dequeue a cell with identifier Cell - must register a nib or a class for the identifier or connect a prototype cell in a storyboard'

Here is my code!

import UIKit

class MasterViewController: UITableViewController, UISearchBarDelegate, UISearchDisplayDelegate {

var detailViewController: DetailViewController? = nil
var objects = [String]()
var filteredObjects = [String]()


override func awakeFromNib() {
    super.awakeFromNib()
    if UIDevice.currentDevice().userInterfaceIdiom == .Pad {
        self.clearsSelectionOnViewWillAppear = false
        self.preferredContentSize = CGSize(width: 320.0, height: 600.0)
    }
}

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    self.navigationItem.leftBarButtonItem = self.editButtonItem()

    let addButton = UIBarButtonItem(barButtonSystemItem: .Add, target: self, action: "insertNewObject:")
    //self.navigationItem.rightBarButtonItem = addButton
    if let split = self.splitViewController {
        let controllers = split.viewControllers
        self.detailViewController = controllers[controllers.count-1].topViewController as? DetailViewController
    }

    objects = ["Person 1", "Person 2", "Person 3", "Person 4"]
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

func insertNewObject(sender: AnyObject) {
    objects.append("Chris Eatough - 23839")
    let indexPath = NSIndexPath(forRow: 0, inSection: 0)
    self.tableView.insertRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic)
}

// MARK: - Segues

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if segue.identifier == "showDetail" {
        let indexPath = self.tableView.indexPathForSelectedRow()
        let object = objects[indexPath.row] as String
        let controller = (segue.destinationViewController as UINavigationController).topViewController as DetailViewController
        controller.detailItem = object
        controller.navigationItem.leftBarButtonItem = self.splitViewController.displayModeButtonItem()
        controller.navigationItem.leftItemsSupplementBackButton = true
    }
}

// MARK: - Table View

override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return 1
}

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    if tableView == searchDisplayController.searchResultsTableView {
        return filteredObjects.count
    }
    else {
        return objects.count
    }
}

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    // this is where the error happens
    let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell

    println("cell has been set to \(cell)")

    var object: String

    if tableView == searchDisplayController.searchResultsTableView {
        object = filteredObjects[indexPath.row] as String
    }
    else {
        object = objects[indexPath.row] as String
    }

    cell.textLabel.text = object
    cell.accessoryType = UITableViewCellAccessoryType.DisclosureIndicator
    return cell
}

override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
    // Return false if you do not want the specified item to be editable.
    return true
}

override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
    if editingStyle == .Delete {
        objects.removeAtIndex(indexPath.row)
        tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
    } else if editingStyle == .Insert {
        // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view.
    }
}

func filterTheObjects(searchString: String!) {
    filteredObjects = objects.filter({(current: String) -> Bool in
        let matchString = (current.rangeOfString(searchString) != nil)

        return matchString
    })
}

func searchDisplayController(controller: UISearchDisplayController!, shouldReloadTableForSearchString searchString: String!) -> Bool {
    filterTheObjects(searchString)

    return true
}

func searchDisplayController(controller: UISearchDisplayController!, shouldReloadTableForSearchScope searchOption: Int) -> Bool {
    filterTheObjects(searchDisplayController.searchBar.text)

    return true
}
}

The same thing happens if I use dequeueReusableCellWithIdentifier instead of dequeueReusableCellWithIdentifier:forIndexPath.

Any thoughts?

Kuldeep
  • 4,466
  • 8
  • 32
  • 59
ubersnack
  • 512
  • 6
  • 19

2 Answers2

0

Make sure you've assigned the identifier "Cell" to something on your XIB/Storyboard

Marcos Duarte
  • 3,472
  • 4
  • 19
  • 22
  • It already is assigned in the storyboard - it works when normally viewing the table, but not when finding a match (see the YT vid) [link](https://www.youtube.com/watch?v=tv1oHYO3OsM) – ubersnack Aug 25 '14 at 16:23
0

I followed the instructions on this previous question searchDisplayController, UITableView, Core Data and Swift and replaced override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { with the following:

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    var cell = tableView.dequeueReusableCellWithIdentifier("Cell") as? UITableViewCell

    if !(cell != nil) {
        cell = UITableViewCell(style: UITableViewCellStyle.Value1, reuseIdentifier: "Cell")
    }

    var object: String

    if tableView == searchDisplayController.searchResultsTableView {
        object = filteredObjects[indexPath.row] as String
    }
    else {
        object = objects[indexPath.row] as String
    }

    cell!.textLabel.text = object
    cell!.accessoryType = UITableViewCellAccessoryType.DisclosureIndicator

    return cell!
}
Community
  • 1
  • 1
ubersnack
  • 512
  • 6
  • 19