Filter in ForEach SwiftUI

Hello

I implemented the filter function in my ForEach loop, and it works just with the valori property but not with the date property , is there a way to let it filter also the date?

I tried to remove the dateFormatter but it didn't work.

Here is the code

import SwiftUI


let dateFormatter: DateFormatter = {
    let formatter = DateFormatter()
    formatter.dateStyle = .medium
    return formatter
}()


struct Test4: View {
    
    @State private var text: String = ""
    
    var body: some View {
            NavigationView{
                if !lifetimes.isEmpty{
                    List{
                        Section(header: Text("")){
                            TextField("Search", text: $text)
                        }
                        
                        Section(header: Text("")){
                            ForEach(lifetimes.filter { text.isEmpty || "\($0)".contains(text) }, id: \.id){ lifetimeInputs in
                                HStack{
                                    Text("\(lifetimeInputs.valori, specifier: "%.0f")")
                                    Spacer()
                                    Text("\(dateFormatter.string(from: lifetimeInputs.date))")
                                }
                            }
                        }
                    }
                    .listStyle(InsetGroupedListStyle())
                    .navigationTitle("All History")
                } else{
                    VStack{
                        Text("No Data")
                            .font(.largeTitle)
                            .fontWeight(.semibold)
                            .foregroundColor(.secondary)
                    }
                    .padding(.bottom)
                    .navigationTitle("All History")
                }
            }
    }
}

struct LifetimeInputsModel: Identifiable {
    var id = UUID()
    var valori: Double
    var date: Date
}

var lifetimes: [LifetimeInputsModel] = [
    LifetimeInputsModel(valori: 300, date: Date()),
    LifetimeInputsModel(valori: 200, date: Date() + 86400)
]

Thank you

Answered by OOPer in 678820022

it works just with the valori property but not with the date property

Seems the description is not correct enough. When I input 2021 into the textField, the list keeps showing the entries containing 2021.


You are using "\($0)".contains(text) for filtering, but do you really understand what sort of Strings are generate by "\($0)"?

As far as I tested with Xcode 12.5/iOS 14.5 Simulator, they were as follows:

LifetimeInputsModel(id: FB973EBF-D56B-438D-BB8B-5EFDFA63983A, valori: 300.0, date: 2021-06-13 21:35:27 +0000)
LifetimeInputsModel(id: 3A57A94C-79EA-4430-90B6-D415C460C243, valori: 200.0, date: 2021-06-14 21:35:27 +0000)

Do you want to make the word LifetimeInputsModel hit all entries?


Apps should not rely on the default String representations generated by Swift runtime.

One possible way, to control the String representation of a struct would be adding CustomStringConvertible conformance.

Please try adding this extension to your project and see if the filter works as expected:

extension LifetimeInputsModel: CustomStringConvertible {
    var description: String {
        return "\(String(format: "%.0f", valori)) \(dateFormatter.string(from: date))"
    }
}

Where is the filter on valori ? How do you want to filter on date ? Matching a date, in a range ?

Accepted Answer

it works just with the valori property but not with the date property

Seems the description is not correct enough. When I input 2021 into the textField, the list keeps showing the entries containing 2021.


You are using "\($0)".contains(text) for filtering, but do you really understand what sort of Strings are generate by "\($0)"?

As far as I tested with Xcode 12.5/iOS 14.5 Simulator, they were as follows:

LifetimeInputsModel(id: FB973EBF-D56B-438D-BB8B-5EFDFA63983A, valori: 300.0, date: 2021-06-13 21:35:27 +0000)
LifetimeInputsModel(id: 3A57A94C-79EA-4430-90B6-D415C460C243, valori: 200.0, date: 2021-06-14 21:35:27 +0000)

Do you want to make the word LifetimeInputsModel hit all entries?


Apps should not rely on the default String representations generated by Swift runtime.

One possible way, to control the String representation of a struct would be adding CustomStringConvertible conformance.

Please try adding this extension to your project and see if the filter works as expected:

extension LifetimeInputsModel: CustomStringConvertible {
    var description: String {
        return "\(String(format: "%.0f", valori)) \(dateFormatter.string(from: date))"
    }
}
Filter in ForEach SwiftUI
 
 
Q