Searching in Categories array

Hello all, Im working on my project and stuck at point of searching through the tableView. I can't figure out how to change my code to filter position in my Categories (name and code). At this moment Search bar filters only Categories name, without category content.

Array:

var categories: [Category] = [

        Category(name: "Name", sign: [Sign(code: "code", name: "name", description: "description", picture: "picture"),

My searchbar func which filter only categories ([Category])

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {

        filteredCategories = []

        if searchText == "" {

            filteredCategories = categories

        } else {

            for signs in categories {

            if signs.name.lowercased().contains(searchText.lowercased()) {

                    filteredCategories.append(signs)
                }
            }
        }

        self.tableView.reloadData()

    }

Thanks for your advices

It's unclear what you mean by "filter position in my Categories". What exactly are you trying to filter on?

Note that in your for loop:

for signs in categories

the signs variable is actually a Category, not a Sign, which makes the code a bit confusing. If you're trying to filter on (say) code and name in the Sign struct, then you could do something like this:

let text = searchText.lowercased()
for category in categories {
    for sign in category.sign {
        if sign.name.lowercased().contains(text) || sign.code.lowercased().contains(text) {
            filteredCategories.append(category)
        }
    }
}

Note that category.sign is a bit odd if the sign property is an array. It might better be called signs.

Thank you for your answer. After changes in codes the result looks the same. To make it more clear I have tableView which include array with structs. Typing in search bar still filter me just name of Category with all Sign positions, instead of searched Sign what is my point.

class Sign {

    let code: String

    let name: String

    let description: String

    let picture: String

    

    init(code: String, name: String, description: String, picture: String) {

        self.code = code

        self.name = name

        self.description = description

        self.picture = picture

    }

}
class Category {

    let name: String

    let sign: [Sign]

    

    init(name: String, sign: [Sign]) {

        self.name = name

        self.sign = sign

    }

}

Looking for showing name from Sign in my table after typing in search bar. I think your code is closer but still append category. Eg.

var categories: [Category] = [

        Category(name: "X", sign: [Sign(code: "X-1", name: "***"),
        Category(name: "Y", sign: [Sign(code: "Y-1", name: "Yyy"),

After typing "yy" || "y" in search bar I need my tableView shows only Sign which contains "yy".

You should show your tableView delegate func

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

as well as

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

Maybe you use categories instead of filteredCategories?

My current TableView configuration:

override func numberOfSections(in tableView: UITableView) -> Int {

        

        return filteredCategories.count

        

    }



    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

        

        return filteredCategories[section].sign.count

    }

    

    override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {

        switch section {

        case 0:

            return filteredCategories[0].name

        case 1:

            return filteredCategories[1].name

        case 2:

            return filteredCategories[2].name

        case 3:

            return filteredCategories[3].name

        default:

            return "Error"

        }

    }

    

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

        

        let cell = tableView.dequeueReusableCell(withIdentifier: PropertyKeys.categorieCell, for: indexPath) as! SignTableViewCell

        

        let categorie = filteredCategories[indexPath.section]

        let sign = categorie.sign[indexPath.row]



        cell.signImagemin.image = UIImage(named: sign.picture)

        cell.signCodeMin.text = sign.code

        cell.signDescriptionMin.text = sign.name

        

        return cell

    }

I think the problem is that you do not filter correctly.

You should do something like this (I changed names to make it more readable):

for categorie in categories {
     if categorie.name.lowercased().contains(searchText.lowercased()) {
        let signs = categorie.sign.filter() { $0.name.contains(searchName) } // If you search for searchName as well
        let newCat = categorie
        newCat.sign = signs  // signs are now filtered

        filteredCategories.append(newCat)
      }
}

Still tableView shows result of this class:

class Category {

    let name: String

    var sign: [Sign]

    

    init(name: String, sign: [Sign]) {

        self.name = name

        self.sign = sign

    }

}

instead of this one:

class Sign {

    let code: String

    let name: String
    

    init(code: String, name: String) {

        self.code = code

        self.name = name

    }

}

I'm really confused by the information you present.

In tableView you have:

        let categorie = filteredCategories[indexPath.section]
        let sign = categorie.sign[indexPath.row]
        cell.signImagemin.image = UIImage(named: sign.picture)
        cell.signCodeMin.text = sign.code
        cell.signDescriptionMin.text = sign.name

So cell is filled up with sign (code and name). So I just don't understand.

Could you show screenshots of the filtered table and what you should want to get.

Eg.: In this tableView

Want to see only signs which contain "A1" and Cat A above as section name

I solved the problem with searching, but now my tableView doesn't back to the original content. I see results but, when searchbar is empty I see original content + filtered. I can't figure out how to link searching with the filteredCategories and avoid touching to the original one.

 func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {

        

        let searchText = searchText.lowercased()

        

        if searchText == "" {

            filteredCategories = categories



        } else {

            for categorie in categories {

                if categorie.sign.filter({$0.name.contains(searchText)}).count != 0 {

                    let signs = categorie.sign.filter() { $0.name.contains(searchText.lowercased()) }

                    let newCat = categorie

                    newCat.sign = signs

                    filteredCategories.append(newCat)

                }

            }

        }

        

        self.tableView.reloadData()

    }
Searching in Categories array
 
 
Q