Tom G
Tom G

Reputation: 133

Search bar and sections in tableview using swift3

I have tableview with alphabetic sections from my database and I want to add search bar but i can't figure it out how to filter the data and implement it in the tableview. My database store inside two structs:

one struct holding all the data.

second struct gets the first letter for the sections and the first struct as array.

My structs:

struct SentenceInfo { // First struct (holds all the data)

    let name: String
    let detail: String
    let sentence: String

    init(name: String, detail: String, sentence: String) {
        self.name = name
        self.detail = detail
        self.sentence = sentence
    }
}

struct SentenceNameSection { // Second struct (first letter and array of the first struct)

    var firstLetter: String
    var crimes: [SentenceInfo]

    init(title: String, objects: [SentenceInfo]) {
        firstLetter = title
        crimes = objects
    }
}

My tableView:

var sections : [SentenceNameSection]!

var crimeData = [SentenceNameSection]()

var filteredData = [SentenceNameSection]()

var shouldShowSearchResults = false

var searchController: UISearchController!


func updateSearchResults(for searchController: UISearchController) {

    let searchString = searchController.searchBar.text

    filteredData = crimeData.filter({ (crime) -> Bool in
        let crimeMatch: String = crime // Error about types
    return ((crimeMatch.range(of: searchString!) != nil))
    })
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let cell: sentenceTableViewCell = tableView.dequeueReusableCell(withIdentifier: cellIdentifer, for: indexPath) as! sentenceTableViewCell

    let crime: SentenceInfo = sections[indexPath.section].crimes[indexPath.row]

    cell.nameLabel.text = crime.name
    cell.detailLabel.text = crime.detail
    cell.sentenceLabel.text = crime.sentence

    return cell
}

Upvotes: 4

Views: 2289

Answers (2)

Badrinath
Badrinath

Reputation: 355

For Swift 3 , below is the sample code 

Struct BookDetails{
  var title:String?
  var author:String?
}

var filteredSearch:[BookDetails] = []

  filteredSearch = self.bookDetails.filter { (data) -> Bool in
            return data.title?.range(of: searchText, options: String.CompareOptions.caseInsensitive) != nil || data.author?.range(of: searchText, options: String.CompareOptions.caseInsensitive) != nil
        }

Upvotes: 0

vadian
vadian

Reputation: 285082

First of all crimeData contains SentenceNameSection which cannot be compared to String

Apart from that to filter the data source array including sections you have to use a repeat loop and create new SentenceNameSection items

This code searches for all three properties in the SentenceInfo struct

let searchString = searchController.searchBar.text!

filteredData.removeAll() // is mandatory to empty the filtered array
for section in crimeData {
    let filteredContent = section.crimes.filter { $0.name.range(of: searchString) != nil
        || $0.detail.range(of: searchString) != nil
        || $0.sentence.range(of: searchString) != nil 
    }
    if !filteredContent.isEmpty {
        filteredData.append(SentenceNameSection(title: section.firstLetter, objects: filteredContent))
    }
}

Note: Of course you have to handle the search case in all appropriate table view data source and delegate methods.

Upvotes: 2

Related Questions