Home > Blockchain >  Can the SearchBar search the CSV file's DATA?
Can the SearchBar search the CSV file's DATA?

Time:11-28

i'm here to ask help.

I just create a tiny dictionary for self use.

And now i want to add a SearchBar to search the keyword from the CSV file,

and it's not work and i cant find any reference from internet

Here is Preview

My CVS Model Code:

import Foundation


struct Model: Identifiable {
    let id: Int
    let Vocab: String
    let Type1 : String
    let Type2 : String
    let Meaning: String
    let Meaning2: String
    
    
    init(raw:[String]){
        self.id =  Int(raw[0])!
        self.Vocab = raw [1]
        self.Type1 = raw[2]
        self.Type2 = raw[3]
        self.Meaning = raw[4]
        self.Meaning2 = raw[5]
        
    }
}

Handle CSV Code:

import Foundation

func cleanRows(file:String) -> String{
    var cleanFile = file
    cleanFile = cleanFile.replacingOccurrences(of: "\r", with: "\n")
    cleanFile = cleanFile.replacingOccurrences(of: "\n\n", with: "\n")
    return cleanFile
}

func loadCSVData() ->[Model]{
    var csvToStruct = [Model]()
    
    guard let filePath = Bundle.main.path(forResource: "Book2", ofType:"csv") else {
        print("Error: file not found")
        return []
    }
    
    var data = ""
    do{
        data = try String(contentsOfFile: filePath)
    } catch{
        print(error)
        return []
    }
    
    data = cleanRows(file: data)
    
    var rows = data.components(separatedBy: "\n")
    
    rows.removeFirst()
    
    for row in rows {
        let csvColumns = row.components(separatedBy: ",")
        if csvColumns.count == rows.first?.components(separatedBy: ",").count{
            let linesStruct = Model.init(raw:csvColumns)
            csvToStruct.append(linesStruct)
        }
    }
    
    
    return csvToStruct
}

Content:

import SwiftUI



struct ContentView: View {
    
    @State var Modelx:[Model]
    @State private var searchText = ""

    
    var body: some View{
        
        
        NavigationView{


            List{
                ForEach (Modelx){ model in
                    NavigationLink(destination:{ModelDetailView(thisModel:model)}){
                        HStack{
                            Text("#" String(format: "d", model.id))
                                .font(.subheadline)
                            Text(model.Vocab)
                                .font(.headline)
                            Spacer()
                            reusableTypeView(thisVocabType: model.Type1)
                            
                            if model.Type2 != ""{
                                reusableTypeView(thisVocabType: model.Type2)
                            }
                            
                            
                        }
                    }
                }
            }.navigationTitle("Music Picionary")
                .searchable(text: $searchText)
            
        }
    }
}



struct reusableTypeView: View {
    var thisVocabType:String
    
    
    var body:some View{
        
        Text(thisVocabType)
            .font(.system(size:15))
            .padding(5)
            .background(Color(thisVocabType))
            .cornerRadius(9)
            .foregroundColor(.white)
    }
}

I think the main point is in the Handle CSV file right?

how can i add a SearchBar to search the keyword from the CSV file

thanks everyone help~

CodePudding user response:

The problem is you never use the search test. You must say the list what data you want and how to apply the filter set by searchTest. A example on how to use searchText :

struct ContentView: View {
    @State var models:[Model]
    @State private var searchText = ""
    // use a model list filtered by the searchText
    var filteredModels: [Model] {
        if searchText == "" {
            return models
        }
        return models.filter { model in
            model.meaning.contains(searchText)
        }
    }
    
    init() {
        models = Model.loadCSVData()
    }
    
    var body: some View{
        NavigationView{
            List{
                ForEach (filteredModels){ model in
                    NavigationLink(destination:{ModelDetailView(thisModel:model)}){
                        HStack{
                            Text("#" String(format: "d", model.id))
                                .font(.subheadline)
                            Text(model.vocab)
                                .font(.headline)
                            Spacer()
                            reusableTypeView(thisVocabType: model.type1)
                            
                            if model.type2 != ""{
                                reusableTypeView(thisVocabType: model.type2)
                            }
                            
                            
                        }
                    }
                }
            }.navigationTitle("Music Picionary")
                .searchable(text: $searchText)
                .textInputAutocapitalization(.none)
                .autocorrectionDisabled()
            // here just to suppress autocapitalisation
            // and autocorrection (not needed)
        }
    }
}

Model with its associated functions :

struct Model: Identifiable {
    let id: Int
    let vocab: String
    let type1 : String
    let type2 : String
    let meaning: String
    let meaning2: String
    
    
    init(raw:[String]){
        self.id =  Int(raw[0])!
        self.vocab = raw [1]
        self.type1 = raw[2]
        self.type2 = raw[3]
        self.meaning = raw[4]
        self.meaning2 = raw[5]
        
    }
    
    static func cleanRows(file:String) -> String{
        var cleanFile = file
        cleanFile = cleanFile.replacingOccurrences(of: "\r", with: "\n")
        cleanFile = cleanFile.replacingOccurrences(of: "\n\n", with: "\n")
        return cleanFile
    }
    
    static func loadCSVData() ->[Model]{
        var csvToStruct = [Model]()
        
        guard let filePath = Bundle.main.path(forResource: "Book2", ofType:"csv") else {
            print("Error: file not found")
            return []
        }
        
        var data = ""
        do{
            data = try String(contentsOfFile: filePath)
        } catch{
            print(error)
            return []
        }
        
        data = cleanRows(file: data)
        
        var rows = data.components(separatedBy: "\n")
        
        // compute column number from first row
        let titlesRow = rows.removeFirst()
        let columnCount = titlesRow.components(separatedBy: ",").count
        
        for row in rows {
            let csvColumns = row.components(separatedBy: ",")
            if csvColumns.count == columnCount {
                let linesStruct = Model.init(raw:csvColumns)
                csvToStruct.append(linesStruct)
            }
        }
        
        
        return csvToStruct
    }
}

Note : I made some little changes in property naming using lowercase for first character. I also initialise the models array in ContentView.init. I also put the functions inside the model definition as these are specific to your model.

  • Related