I need some help trying to work with .searchable in Swift UI.
I am trying to present a few pieces of data that are associated with the search string.
For example, the user searches for a certain description, and the code/price is also presented in the row. I do not want to present the data on a new view, just dynamically as the user is typing.
The problem I am having is that I cannot find a way to manipulate the computed value "search results" and also the generic "named: in the ForEach loop.
I understand the "search results" is an array but I can't a way to access it.
The removalAll was added because every time I went back to this view, it duplicated the list every time a character was typed in the search bar.
I have the data as an enum, and stored in an array because at the time it made sense in case I needed to iterate over the data.
Any advice or suggestions to do this?
Thank you in advance!
Here is the main view:
struct ContentView: View {
@State private var searchText = ""
var body: some View {
storedOtherWoundsNames.removeAll()
self.createOtherWound()
return
NavigationView {
List {
ForEach(searchResults, id: \.self) { named in
VStack {
VStack {
Text(named) //search result
.frame(maxWidth: .infinity, alignment: .leading)
.font(.caption)
}
HStack {
Text("\(named) Code") //want to display from the array "storedOtherWoundsCodes"
.frame(maxWidth: .infinity, alignment: .leading)
.font(.caption)
Text("\(named) Value") //want to display from the array "storedOtherWoundsValues"
.frame(maxWidth: .infinity, alignment: .trailing)
}
}
.padding(.all)
.border(Color.gray)
}
}
}
.searchable(text: $searchText)
}
var searchResults: [String] {
if searchText.isEmpty {
storedOtherWoundsNames.removeAll()
return storedOtherWoundsNames
} else {
return storedOtherWoundsNames.filter{$0.contains(searchText)
}
}
}
func createOtherWound() { //takes enum and places it in array
for otherWoundName in allOtherWoundsNames {
storedOtherWoundsNames.append(otherWoundName.rawValue)
}
for otherWoundCode in allOtherWoundsCodes {
storedOtherWoundsCodes.append(otherWoundCode.rawValue)
}
for otherWoundValue in allOtherWoundsValues {
storedOtherWoundsValues.append(otherWoundValue.rawValue)
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Here is the data if it helps:
enum OtherWoundsName: String, CaseIterable {
case secondaryclosure_name = "Secondary Closure"
case musclerepair_name = "Muscle Repair (including skin)"
case woundone_name = "Debride Wound/Ulcer - One"
case woundtwo_name = "Debride Wound/Ulcer - Two"
case woundthree_name = "Debride Wound/Ulcer - Three"
case woundfourmore_name = "Debride Wound/Ulcer - Four Plus"
case debrideone_name = "Debride into Tendon/Bone/Bursa/Bone"
case debridetwo_name = "Debride into Tendon/Bone/Bursa/Bone - Two or More"
case extensortendon_name = "Extensor Tendon Repair"
case flexortendor_name = "Flexor Tendon Repair"
case fbskin_name = "FB Skin"
case fbskinsedation_name = "FB Skin with Sedation"
case fbdermissedation_name = "FB Dermis with Sedation"
case flapface5_name = "Advancement Flap: Neck Up < 5.1cm"
case flapother5_name = "Advancement Flap: Other < 5.1cm"
case flapface5plus_name = "Advancement Flap: Neck up > 10.1cm"
case flapother5plus_name = "Advancement Flap: Other > 10.1.cm"
case fingerdebride_name = "Finger Debridement"
case handdebride_name = "Hand Debridement"
case facedebride_name = "Face Debridement"
case otherdebride_name = "Other per % BSA"
case ampulatephalanx_name = "Amputate Phalanx"
case revisionfingertip_name = "Revision of Amputation Finger Tip"
}
enum OtherWoundsCode: String, CaseIterable {
case secondaryclosure_code = "Z738"
case musclerepair_code = "R525"
case woundone_code = "Z080"
case woundtwo_code = "Z081"
case woundthree_code = "Z082"
case woundfourmore_code = "Z083"
case debrideone_code = "Z084"
case debridetwo_code = "Z085"
case extensortendon_code = "R578"
case flexortendor_code = "R585"
case fbskin_code = "Z114"
case fbskinsedation_code = "Z115"
case fbdermissedation_code = "R517"
case flapface5_code = "R011"
case flapother5_code = "R002"
case flapface5plus_code = "R012"
case flapother5plus_code = "R003"
case fingerdebride_code = "R660"
case handdebride_code = "R661"
case facedebride_code = "R662"
case otherdebride_code = "R637"
case ampulatephalanx_code = "R606"
case revisionfingertip_code = "R629"
}
enum OtherWoundsValue: Double, CaseIterable {
case secondaryclosure_value = 97.35
case musclerepair_value = 88.60
case woundone_value = 20
case woundtwo_value = 30
case woundthree_value = 45
case woundfourmore_value = 60
case debrideone_value = 60.001
case debridetwo_value = 90
case extensortendon_value = 164.10
case flexortendor_value = 307.60
case fbskin_value = 25.20
case fbskinsedation_value = 88.80
case fbdermissedation_value = 107.70
case flapface5_value = 89.85
case flapother5_value = 67.40
case flapface5plus_value = 247.15
case flapother5plus_value = 161.75
case fingerdebride_value = 28.90
case handdebride_value = 47.85
case facedebride_value = 28.901
case otherdebride_value = 29.68
case ampulatephalanx_value = 161.45
case revisionfingertip_value = 241.55
}
let allOtherWoundsNames = OtherWoundsName.allCases
var storedOtherWoundsNames: [String] = []
let allOtherWoundsCodes = OtherWoundsCode.allCases
var storedOtherWoundsCodes: [String] = []
let allOtherWoundsValues = OtherWoundsValue.allCases
var storedOtherWoundsValues: [Double] = []
Try this approach as shown in the example code, where the data is in an array of structs ([DataModel]
), and
the search returns a filtered array that can be used to "access" the name
, code
and value
of each item.
struct ContentView: View {
@State private var searchText = ""
@State var items = [DataModel]()
var searchResults: [DataModel] {
searchText.isEmpty ? [] : items.filter{$0.name.contains(searchText)}
// or alternatively
// searchText.isEmpty ? items : items.filter{$0.name.contains(searchText)}
}
var body: some View {
NavigationView {
List {
ForEach(searchResults) { item in
VStack {
Text(item.name).font(.caption)
HStack {
Text(item.code).font(.caption).foregroundColor(.red)
Text("\(item.value)").foregroundColor(.blue)
}
}
.frame(maxWidth: .infinity, alignment: .leading)
.padding(.all)
.border(Color.gray)
}
}
}
.searchable(text: $searchText)
.onAppear {
items = [DataModel(name: "Secondary Closure", code: "Z738", value: 97.35),
DataModel(name: "Muscle Repair (including skin)", code: "R525", value: 88.60),
DataModel(name: "Debride Wound/Ulcer - One", code: "Z080", value: 20)]
// etc...
}
}
}
struct DataModel: Identifiable {
let id = UUID()
var name: String
var code: String
var value: Double
}