Home > Software engineering >  Make a searchable List from CSV file in Swift UI
Make a searchable List from CSV file in Swift UI

Time:09-03

After long time developing in Swift with storyboard I decide to move to Swift UI. I make a small project to do that. This project is to simply read a CSV file and show some informations in a List and make this list searchable.

I've already been able to read the CSV file and then open some informations in a List. I've understand approximately how the protocol work but I'm definitely looked with the searching function ...

Here is my "mainView" code :

struct AirportView: View {
@State private var searchText = ""
@ObservedObject var airportsVM:AirportsViewModel = AirportsViewModel()
   var body: some View {
       let airportsDB = airportsVM.ListAirports
       NavigationView { 
           List{
               Section(header: Text("Suisse")){
                   Text("Hello World")
               }
               Section(header: Text("France")) {
                   ForEach(airportsDB, id:\.self) { listAirport in
                       
                       NavigationLink(destination: Text(listAirport.ApType)) {
                           Text("\(listAirport.Icao) - \(listAirport.Name)")
                        }
                       
                   }
               }
              
           }
               .id(UUID())
           
       }
       .navigationTitle("Airports")
       .searchable(text: $searchText)
       .navigationViewStyle(StackNavigationViewStyle())
       
   }

and here is my "CSV Reader" Code

    import Foundation

    struct Airports2: Identifiable, Codable, Hashable{
        var AirportID: String = ""
        var Icao: String = ""
        var ApType: String = ""
        var Name: String = ""
        var Latitude: String = ""
        var Longitude: String = ""
        var Altitude: String = ""
        var Continent: String = ""
        var Country: String = ""
        var Region: String = ""
        var Municipality: String = ""
        var Service: String = ""
        var GpsCode: String = ""
        var Iata: String = ""
        var LocalCode: String = ""
        var Link: String = ""
        var wikiLink: String = ""
        var Keyword: String = ""
        let id = UUID()
    }
    var airportsDB = [Airports2]()
    
    class AirportsClass {
        
    
        
        static let 

bundleURL =  Bundle.main.url(forResource: "FR_Airports", withExtension: "csv")!
    static func retrieveAP() -> [Airports2] {
        guard let data = try? Data(contentsOf: bundleURL) else {
            fatalError("Unable to load airports data")
        }
        let decoder = String(data: data, encoding: .utf8)
        if  let dataArr = decoder?.components(separatedBy: "\n").map({ $0.components(separatedBy: ",") })
        {
            var i = 0
            for line in dataArr
            {
                i  = 1
                if i <  dataArr.count  {
                    let item = Airports2(AirportID: line[0], Icao: line[1], ApType: line[2], Name: line[3], Latitude: line[4], Longitude: line[5], Altitude: line[6], Continent: line[7], Country: line[8], Region: line[9], Municipality: line[10], Service: line[11], GpsCode: line[12], Iata: line[13], LocalCode: line[14], Link: line[15], wikiLink: line[16], Keyword: line[17])
                    airportsDB.append(item)
                }
            }
        }
        return airportsDB
    }
    }
    
    class AirportsViewModel: NSObject, ObservableObject {
        @Published var ListAirports = [Airports2]()
        override init() {
            
            ListAirports = AirportsClass.retrieveAP()
        }
    }

Thanks for your help !

CodePudding user response:

struct AirportView: View {
    @State private var searchText = ""
    private let airportsVM = AirportsClass.retrieveAP()

    var filteredResults: [Airports2] {
        if searchText.isEmpty {
          return airportsVM.ListAirports
        } else {
          // some sort of filtering - you'll probably need to filter on multiple properties
          return airportsVM.ListAirpots.filter { $0.Name.contains(searchText) }
        }
    }

    var body: some View {
       NavigationView { 
           List{
               Section(header: Text("Suisse")){
                   Text("Hello World")
               }
               Section(header: Text("France")) {
                   ForEach(filteredResults, id:\.self) { airport in
                       
                       NavigationLink(destination: Text(airport.ApType)) {
                           Text("\(airport.Icao) - \(airport.Name)")
                        }
                       
                   }
               }
              
           }
               .id(UUID())
           
       }
       .navigationTitle("Airports")
       .searchable(text: $searchText)
       .navigationViewStyle(StackNavigationViewStyle())
    }
}
  • Related