Search a list in SwiftUI

Hi there,

I am still quite new to Swift. Is there a easy way to search a list with navigation links to other swift pages?

Thank you so much for your help!

Laurin

Answered by Claude31 in 770305022

You should post code, it would be easier to explain.

But here is a simple example to explain the principles that you should adapt (by changing the List)

struct DataView: View {
    
    var body: some View {
        Text("DataView")
    }
}

struct Data2View: View {
    
    var body: some View {
        Text("Data2View")
    }
}

public var countrylist = ["test1", "test2", "test3"]

struct testView: View {
    
    var countries: [String] {
        
        let lcCountries = listOfCountry.map { $0.lowercased() }
        
        return searchText == "" ? lcCountries : lcCountries.filter {
            $0.contains(searchText.lowercased())
        }
        
    }
    
    private var listOfCountry = countrylist
    @State var searchText = ""
    
    var body: some View {
        
        NavigationView {
            List {
                ForEach(countries, id: \.self) { country in
                    HStack {
                        Text("")
                        Section(header: Text(country.capitalized))
                        {
                            Text("test")
                        }
                        
                        if country.contains("test1") {
                            NavigationLink(destination: DataView()) {
                                Spacer()
                                Image(systemName: "percent")
                            }
                        } else if country.contains("test2"){
                            NavigationLink(destination: Text("test")) {
                                Text("test2")
                            }
                        } else if country.contains("test3"){
                            NavigationLink(destination: Data2View()) {
                                Text("test3")
                            }
                        }
                        
                    }
                    
                }
                
            }
            
            .searchable(text: $searchText)
            .navigationTitle("testview")
            .navigationBarTitleDisplayMode(.inline)
            
        }
        
    }
    
}
Accepted Answer

You should post code, it would be easier to explain.

But here is a simple example to explain the principles that you should adapt (by changing the List)

struct DataView: View {
    
    var body: some View {
        Text("DataView")
    }
}

struct Data2View: View {
    
    var body: some View {
        Text("Data2View")
    }
}

public var countrylist = ["test1", "test2", "test3"]

struct testView: View {
    
    var countries: [String] {
        
        let lcCountries = listOfCountry.map { $0.lowercased() }
        
        return searchText == "" ? lcCountries : lcCountries.filter {
            $0.contains(searchText.lowercased())
        }
        
    }
    
    private var listOfCountry = countrylist
    @State var searchText = ""
    
    var body: some View {
        
        NavigationView {
            List {
                ForEach(countries, id: \.self) { country in
                    HStack {
                        Text("")
                        Section(header: Text(country.capitalized))
                        {
                            Text("test")
                        }
                        
                        if country.contains("test1") {
                            NavigationLink(destination: DataView()) {
                                Spacer()
                                Image(systemName: "percent")
                            }
                        } else if country.contains("test2"){
                            NavigationLink(destination: Text("test")) {
                                Text("test2")
                            }
                        } else if country.contains("test3"){
                            NavigationLink(destination: Data2View()) {
                                Text("test3")
                            }
                        }
                        
                    }
                    
                }
                
            }
            
            .searchable(text: $searchText)
            .navigationTitle("testview")
            .navigationBarTitleDisplayMode(.inline)
            
        }
        
    }
    
}

Thank you for your answer, @Claude31 . Here is my code. The problem is that I have no variables. Can I implement them?

Laurin

    var body: some View {
        NavigationView {
            List {
                Group {
                    Section (header: Text("Grundlagen")){
                        NavigationLink(destination: StandardVorgehenInvasiveMassnahmen())
                        {
                            Label {
                                Text("Standardvorgehen bei invasiven Maßnahmen")
                            } icon: {
                                Image(systemName: "list.bullet.clipboard")
                            }
                        }
                    }
                    Section (header: Text("Zugang")){
                        NavigationLink(destination: ivZugang())
                        {
                            Label {
                                Text("i.v.-Zugang")
                            } icon: {
                                Image(systemName: "syringe")
                            }
                        }
                        NavigationLink(destination: ioZugangEZIO())
                        {
                            Label {
                                Text("i.o.-Zugang: EZ-IO® / COOK® / BIG®")
                            } icon: {
                                Image(systemName: "syringe.fill")
                            }
                        }
                        NavigationLink(destination: ioZugangFAST1())
                        {
                            Label {
                                Text("i.o.-Zugang: FAST1®")
                            } icon: {
                                Image(systemName: "syringe.fill")
                            }
                        }
                        
                    }
                    Section (header: Text("Extraglottischer Atemweg")){
                        NavigationLink(destination: extraglottischerAtemweg())
                        {
                            Label {
                                Text("Extraglottischer Atemweg")
                            } icon: {
                                Image(systemName: "lungs")
                            }
                        }
                        NavigationLink(destination: extraglottischerAtemwegLTSD())
                        {
                            Label {
                                Text("Extraglottischer Atemweg: LTS-D®")
                            } icon: {
                                Image(systemName: "lungs.fill")
                            }
                        }
                        NavigationLink(destination: Larynxmaske())
                        {
                            Label {
                                Text("Larynxmaske mit Drainagekanal")
                            } icon: {
                                Image(systemName: "lungs")
                            }
                        }
                        NavigationLink(destination: extraglottischerAtemwegIGEL())
                        {
                            Label {
                                Text("Extraglottischer Atemweg: i-gel®")
                            } icon: {
                                Image(systemName: "lungs.fill")
                            }
                        }
                        
                    }
                }
                    Section (header: Text("Weitere invasive Maßnahmen")){
                        Group {
                            NavigationLink(destination: LaryngoskopieMagillzange())
                            {
                                Label {
                                    Text("Laryngoskopie / Magillzange")
                                } icon: {
                                    Image(systemName: "lungs")
                                }
                            }     
                    }
                }
            }
            .listStyle(SidebarListStyle())
            .navigationTitle("Maßnahmen")
            .toolbar {
                NavigationLink(destination: About()){
                    Image(systemName: "info.circle")
                }
            }
            
            BackgroundMassnahmen()
        }
    }
}

You have to adapt to you code.

Create the var:

struct ContentView: View {
    
    var medics: [String] {
        
        let lMedics = listOfMedics.map { $0.lowercased() }
        
        return searchText == "" ? lMedics : lMedics.filter {
            $0.contains(searchText.lowercased())
        }
        
    }
    
    private var listOfMedics = medicList
    @State var searchText = ""

Then change code:

Section (header: Text("Zugang")){
    ForEach(medics, id: \.self) { medic in
        if medic.contains("medic1") {
            NavigationLink(destination: ivZugang()) {
                Label {
                    Text("i.v.-Zugang")
                } icon: {
                    Image(systemName: "syringe")
                }
            }
        } else if medic.contains("medic2"){
            NavigationLink(destination: ioZugangEZIO()) {
                Label {
                    Text("i.o.-Zugang: EZ-IO® / COOK® / BIG®")
                } icon: {
                    Image(systemName: "syringe.fill")
                }
            }
        } else if medic.contains("medict3"){
            NavigationLink(destination: ioZugangFAST1()) {
                Label {
                    Text("i.o.-Zugang: FAST1®")
                } icon: {
                    Image(systemName: "syringe.fill")
                }
            }
        }

    }

and at the end:

            .searchable(text: $searchText)
            .navigationTitle("Maßnahmen")
            .navigationBarTitleDisplayMode(.inline)

@Claude31 Thank you for your answer! As you know I am really new to this all and I have this error message:

What am I doing wrong?

Best, Laurin

Hey Laurin!

@Claude31 has given you a great jumping off point. To add on for a little clarity, you'll need an array of your NavigationLink titles, which it seems like he has called medicList. Essentially, your code should look like this:

struct ContentView: View {
    let medicList = ["i.v.-Zugang", ...] //this should be an array of your navigation link titles, I've left it as ... for you to fill in
    @State private var searchText = ""

    var body: some View {
        NavigationStack {
            List (medicList, id: \.self) { medic in
                    NavigationLink {
                        Text(medic) //destination here
                    } label: {
                        Text(medic)
                  }
            }
            .navigationTitle("medics")
        }
        .searchable(text: $searchText)            
    }

    var searchResults: [String] {
        if searchText.isEmpty {
            return medicList
        } else {
            return medicList.filter { $0.contains(searchText) }
        }
    }
}

Having a @State searchText variable allows you to store the text you are searching and check if it is in the array. To check this, you can use filter to "filter" the list based on if the item in the list contains the text you have searched.

Passing the array into the List loops through each item in the array and create a NavigationLink programmatically for each String in the array.

Lastly, I'd like to point out that this uses NavigationStack instead of NavigationView, which is a newer API as of iOS 16. Please use this unless you are supporting iOS 15 or earlier.

@sha921 Thank you very much for your help. I still have got some problems. I implemented the code as you said, but unfortunately I still do not get any results when I try to search something. Furthermore I don't know how I can link the results to already existing views with NavigationLink. Could you help me once more?

Thanks! Here is my code:

    
    let medicList = ["Acetylsalicylsäure",
                     "Amiodaron",
                     "Atropin",
                     "Butylscopolamin",
                     "Dimenhydrinat",
                     "Dimentinden",
                     "Epinephrin",
                     "Esketamin",
                     "Furosemid",
                     "Glucagon",
                     "Glucose",
                     "Glyceroltrinitrat",
                     "Heparin",
                     "Ibuprofen",
                     "Ipratropiumbromid",
                     "Lidocain",
                     "Midazolam",
                     "Naloxon",
                     "Paracetamol",
                     "Prednisolon",
                     "Salbutamol",
                     "Sauerstoff",
                     "Urapidil",
                     "Vollelektrolytlösung"]
    
    @State private var searchText = ""
    
    
    var body: some View {
        NavigationView {
            List (medicList, id: \.self) { medic in
                NavigationLink {
                    Text(medic) //destination here
                } label: {
                    Text(medic)
                }
            }
            .navigationTitle("Medikamente")
        }
        .searchable(text: $searchText)
    }


var searchResults: [String] {
        if searchText.isEmpty {
            return medicList
        } else {
            return medicList.filter { $0.contains(searchText) }
        }
    }
}
Search a list in SwiftUI
 
 
Q