Home > Software design >  Making a ForEach List searchable in Xcode 13
Making a ForEach List searchable in Xcode 13

Time:11-15

I have a list that is parsed from a csv file for map coordinates. I'm having trouble getting the search function to work. I'm trying to use the new .searchable addition to Xcode 13. Nothing I've tried so far works. The search bar and navigation title shows up. What am I missing? Thanks.

'''
import SwiftUI
import MapKit

struct SiteView: View {
    
    var sites = loadCSV(from: "csv")
    @State private var searchText: String = ""
    var body: some View {
        NavigationView {
            List {
                
                ForEach(sites) { site in
                        
            let latitude = (site.latNum as NSString).doubleValue
            let longitude = (site.longNum as NSString).doubleValue
            let url = URL(string:"http://maps.apple.com/maps?saddr=&daddr=\(latitude),\(longitude)")
                    
                    Button(site.siteName, action: {UIApplication.shared.open(url!)})
                    
                        
        }
    }
            
            .navigationTitle("Sites")
            .searchable(text: $searchText)

            }
        }
    }
    
struct SiteView_Previews: PreviewProvider {
    static var previews: some View {
        SiteView()

    }
}
'''

EDIT

I have tried different methods of search filtering, like this:

    }

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

With this method I replaced ‘names’ with ‘sites’ and I keep getting cannot convert to String errors. I assumed it was because I have ‘sites’ defined as a loadable csv and not a standard string like in the example.

Another method I found was this:

struct ContentView: View {

    @State private var searchQuery: String = ""

    var body: some View {
        NavigationView {
            List {
                ForEach(Array(1...100)
                            .map { "\($0)" }
                            .filter { searchQuery.isEmpty ? true : $0.contains(searchQuery) }
                        ,id: \.self) { item in
                    Text(verbatim: item)
                }
            }
            .navigationTitle("Fancy Numbers")
            .searchable(text: $searchQuery)
        }
    }

}

This seemed more like what I need in that it does the filtering within the list, but I’m not familiar enough with the syntax to get it to work. I don’t think I need the (Array(1…100) and assume I need to alter it so it will work with my parsed list.

I know it’s probably a really simple solution, and I could be going about it all wrong.

CodePudding user response:

Here is one of the examples with a computed property that does the filtering.

struct SiteView: View {
    let sites = loadCSV(from: "csv")
    @State private var searchText: String = ""
    
    var searchResults: [Sites] {
        if searchText.isEmpty {
            return sites
        }
        return sites.filter { $0.siteName.contains(searchText) }
    }
    
    var body: some View {
        NavigationView {
            List {
                ForEach(searchResults) { site in
                    let latitude = (site.latNum as NSString).doubleValue
                    let longitude = (site.longNum as NSString).doubleValue
                    let url = URL(string:"http://maps.apple.com/maps?saddr=&daddr=\(latitude),\(longitude)")
                    
                    Button(site.siteName, action: {UIApplication.shared.open(url!)})
                }
            }
            .navigationTitle("Sites")
            .searchable(text: $searchText)                
        }
    }
}
  • Related