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
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.