I have successfully build a search function which searches and displays the TableView title and and subtitle in a detailviewcontroller. In the detailviewcontroller there's two text labels, one for the title and one for the subtitle.
Displaying the title and subtitles in the cells works fine, including tapping and seeing them in the detailviewcontroller. But when typing in the search function the app crashes due to:
fatal error: Array index out of range (lldb)
EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
Here's all my code:
let quotes = [
"Saying1",
"Saying2",]//End
let persons = [
"Name1",
"Name2",
]//End
var filteredQuotes = [String]()
var filteredPersons = [String]()
var resultSearchController = UISearchController()
override func viewDidLoad() {
super.viewDidLoad()
self.resultSearchController = UISearchController(searchResultsController: nil)
self.resultSearchController.searchResultsUpdater = self
self.resultSearchController.dimsBackgroundDuringPresentation = false
self.resultSearchController.searchBar.sizeToFit()
self.tableView.tableHeaderView = self.resultSearchController.searchBar
self.tableView.reloadData()
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1 }
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
if self.resultSearchController.active
{
return self.filteredQuotes.count
}
else
{
return self.quotes.count
}
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as UITableViewCell?
if self.resultSearchController.active
{
cell!.textLabel?.text = self.filteredQuotes[indexPath.row]
cell!.detailTextLabel?.text = self.filteredPersons[indexPath.row] //THE ERROR OCCURS HERE
}
else
{
cell!.textLabel?.text = self.quotes[indexPath.row]
cell!.detailTextLabel?.text = self.persons[indexPath.row]
}
return cell!
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "SendDataSegue" {
if let destination = segue.destinationViewController as? SearchDetailViewController {
let path = tableView.indexPathForSelectedRow
let cell = tableView.cellForRowAtIndexPath(path!)
destination.viaSegue = (cell?.textLabel?.text!)!
destination.viaSeguePerson =(cell?.detailTextLabel?.text!)!
}
}
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
_ = tableView.indexPathForSelectedRow!
if let _ = tableView.cellForRowAtIndexPath(indexPath) {
self.performSegueWithIdentifier("SendDataSegue", sender: self)
}
}
func updateSearchResultsForSearchController(searchController: UISearchController) {
self.filteredQuotes.removeAll(keepCapacity: false)
self.filteredPersons.removeAll(keepCapacity: false)
let searchPredicate = NSPredicate(format: "SELF CONTAINS [c] %@", searchController.searchBar.text!)
let Quotesarray = (self.quotes as NSArray).filteredArrayUsingPredicate(searchPredicate)
self.filteredQuotes = Quotesarray as! [String]
let Personsarray = (self.persons as NSArray).filteredArrayUsingPredicate(searchPredicate)
self.filteredPersons = Personsarray as! [String]
self.tableView.reloadData()
}
xcodeand addswift).filteredPersonscontain the data you think it contains? Have you logged the contents? Why are you storing data in 2 separate arrays? It looks to me like a quote belongs to a person right? Why not make an object calledQuotethat contains a String for the quote and a String for the name? Then you only need one array calledquotesor something.QuotesarrayandPersonsarraycontains the same amount (and the corresponding ones by the way) data? Ex: Quotes with @"I think; therefore I am", and so Persons with "René Descartes", and you search "Descartes", what shouldQuotesarrayandPersonsarrayhave?