128K
128K

Reputation: 63

UISearchBar not working with sub sections in array

I am using an array variable called sections as the table view has collapsable sections:

var sections = [

        // TESTING CODE FOR SECTIONS
        Section(sec: "One",
                subSec: ["A", "B", "C", "D", "E"],
                expanded: false),

        Section(sec: "Two",
                subSec: ["A", "B", "C", "D", "E"],
                expanded: false),

        Section(sec: "Three",
                subSec: ["A", "B", "C", "D", "E"],
                expanded: false),

I am trying to use UISearchController to make the table view searchable. Here is what I have tried so far but its not working:

func filterContentForSearchText(_ searchText: String, scope: String = "All") {
  filtered = sections.filter({( section : Section) -> Bool in
    return section.subSec.name.lowercased().contains(searchText.lowercased())
  })

  tableView.reloadData()
}

I understand how the function works but cannot seem to get it to work with my subSec in the variable.

//SEARCH
    var filteredSections: [String]?
    let searchController = UISearchController(searchResultsController: nil)


    override func viewDidLoad() {
        super.viewDidLoad()

        //SEARCH
        filteredSections = sections
        searchController.searchResultsUpdater = self
        searchController.hidesNavigationBarDuringPresentation = false
        searchController.dimsBackgroundDuringPresentation = false
        tableView.tableHeaderView = searchController.searchBar

    }

I get errors such as 'cannot assign value of type '[Section]' to type '[String]?' I understand why, but I don't know how to resolve this.

Section definition:

struct Section {
    var sec: String!
    var subSec: [String]! // [ ] = Array of Strings
    var expanded: Bool!

    init(sec: String, subSec: [String], expanded: Bool) {
        self.sec = sec
        self.subSec = subSec
        self.expanded = expanded
    }
}

Upvotes: 1

Views: 60

Answers (1)

David Pasztor
David Pasztor

Reputation: 54706

filteredSections is an array of Strings and you are trying to assign the output of a filter function called on an array of Sections, which return an array of Sections, so it obviously won't work.

If you want to return Strings as a result of filtering the array of Sections, you need to combine filter and map, which can be done with a single flatMap.

The ternary operator inside the flatMap checks the same condition as your filter did, but it returns section.subSec.name if the condition evaluates to true and nil otherwise, which the flatMap simply ignores, hence the output array will only contain the matching subsection names.

func filterContentForSearchText(_ searchText: String, scope: String = "All") {
  filtered = sections.flatMap{ return $0.subSec.name.lowercased().contains(searchText.lowercased()) ? searchText : nil }

  tableView.reloadData()
}

Since you didn't include the definition of Section in your code, I couldn't test the function, but if subSec.name is a String, it will work just fine.

Upvotes: 1

Related Questions