arraysswiftuisearchbarswift-structs

How do I use .filter for an array with structs in Swift?


I am setting up a UISearchBar for my mathematics app. The search bar is supposed to search through an array allItems to find what the user is searching. The array allItems uses a struct called Headline to define an item ID and an item Title. When I try to fill out the UISearchBar textDidChange func, I get this error: Cannot assign value of type '[Headline]' to type '[String?]'

My code is attached below:

For the array and struct setup-

struct Headline {
    var id: Double
    var title: String
}


let allItems = invest+geoArea+geoVolume+geoSA+geoLSA+advPythag+advPhysics+advConv+advOther

The arrays that makes up allItems are using the struct Headline

For the UISearchBar-

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
        searchCalc = allItems.filter({$0.title.lowercased().prefix(searchText.count) == searchText.lowercased()})
        isSearching = true
        tableView.reloadData()
    }

Other Helpful Code:

var searchCalc = [String?]()

The isSearching Bool is just to help the app know when the user is actively searching for something

Also, searchCalc is the variable used to store what the user is currently searching. It is supposed to be string so that the app can filter out array items based on what the user is typing.

And this code block will be long, but it might help make more sense. Below is the code used to create all of the arrays inside allItems-

let invest = [
    Headline(id: 1.01, title: "Simple Interest"),
    Headline(id: 1.02, title: "Compound Interest"),
    Headline(id:1.03, title: "Car Loan")
]
let geoArea = [
    Headline(id: 2.01, title: "Triangle"),
    Headline(id: 2.02, title: "Rectangle"),
    Headline(id: 2.03, title: "Parallelogram"),
    Headline(id: 2.04, title: "Circle")
]
let geoVolume = [
    Headline(id: 2.11, title: "Cube"),
    Headline(id: 2.12, title: "Cone"),
    Headline(id: 2.13, title: "Cylinder"),
    Headline(id: 2.14, title: "Sphere")
]
let geoSA = [
    Headline(id: 2.21, title: "Cube"),
    Headline(id: 2.22, title: "Rectangular Prism"),
    Headline(id: 2.23, title: "Cylinder"),
    Headline(id: 2.24, title: "Triangular Prism")
]
let geoLSA = [
    Headline(id: 2.31, title: "Rectangular Prism"),
    Headline(id: 2.32, title: "Cylinder")
]
let advPythag = [
    Headline(id: 3.01, title: "Hypotenuse"),
    Headline(id: 3.02, title: "Leg")
]
let advPhysics = [
    Headline(id: 3.11, title: "Speed"),
    Headline(id: 3.12, title: "Acceleration")
]
let advConv = [
    Headline(id: 3.21, title: "Feet to Meters"),
    Headline(id: 3.22, title: "Meters to Feet"),
    Headline(id: 3.23, title: "Mile to Kilometer"),
    Headline(id: 3.24, title: "Kilometer to Mile"),
    Headline(id: 3.25, title: "Gallon to Liter"),
    Headline(id: 3.26, title: "Liter to Gallon"),
    Headline(id: 3.27, title: "Fraction to Decimal"),
    Headline(id: 3.28, title: "Feet to Inches"),
    Headline(id: 3.29, title: "Inches to Feet"),
    Headline(id: 3.210, title: "Fahrenheit to Celsius"),
    Headline(id: 3.211, title: "Celsius to Fahrenheit"),
]
let advOther = [
    Headline(id: 3.31, title: "Square Root")
]

Solution

  • Your searchCalc is of type [String?], therefore you can't assign a subset of your allItems array. You can solve the problem by just grabbing the titles from the allItems array.

    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
        searchCalc = [String]()
        let matches = allItems.filter({$0.title.lowercased().prefix(searchText.count) == searchText.lowercased()})
        for match in matches{
            searchCalc.append(match.title)
        } 
        isSearching = true
        tableView.reloadData()
    }