GO FURTHER, FASTER: Try the Swift Career Accelerator today! >>

Can't filter SwiftData @Query based on an @EnvironmentObject

Forums > SwiftUI

I have this class Filters:

class Filters: ObservableObject {
    @Published var visited: Bool? = nil
    @Published var ratingMin: Int? = 0
    @Published var ratingMax: Int? = 5
    @Published var priceMin: Int? = 0
    @Published var priceMax: Int? = 3
    @Published var searchText = ""
    @Published var sortOrder = SortDescriptor(\Place.rating)
}

And I want to filter the following query:

@Query var places: [Place]

First I tried to do it in the init{} method but @EnvironmentObject are never available in init methods.

Then I tried to modify the query in .onAppeat() but that is not possible either

Could anyone help me with a suggestion on how to fix this?

Thanks in advance

1      

Hi Jose,

I understand the challenge you’re facing with filtering @Query based on @EnvironmentObject. Here’s a solution you can try:

Using a Custom Filtering Function Since @EnvironmentObject isn’t directly accessible in @Query, consider filtering your results manually using a custom function in your view. Here’s a step-by-step approach:

Define a Filter Function:

Create a function in your view to filter the results based on the properties in your Filters object. This function will be called whenever the view needs to update its display.

swift Copy code func filterPlaces(places: [Place], filters: Filters) -> [Place] { return places.filter { place in (filters.visited == nil || place.visited == filters.visited) && (filters.ratingMin == nil || place.rating >= filters.ratingMin!) && (filters.ratingMax == nil || place.rating <= filters.ratingMax!) && (filters.priceMin == nil || place.price >= filters.priceMin!) && (filters.priceMax == nil || place.price <= filters.priceMax!) && (filters.searchText.isEmpty || place.name.contains(filters.searchText)) } } Apply the Filter in Your View:

Use the filter function within your view’s body to display the filtered results.

swift Copy code var body: some View { List { ForEach(filterPlaces(places: places, filters: filters)) { place in Text(place.name) } } } Observe Filter Changes:

Make sure your view updates whenever the filters change by observing the Filters object.

swift Copy code @EnvironmentObject var filters: Filters Example Implementation: swift Copy code struct PlaceListView: View { @EnvironmentObject var filters: Filters @Query var places: [Place]

var body: some View {
    List {
        ForEach(filterPlaces(places: places, filters: filters)) { place in
            Text(place.name)
        }
    }
}

func filterPlaces(places: [Place], filters: Filters) -> [Place] {
    return places.filter { place in
        (filters.visited == nil || place.visited == filters.visited) &&
        (filters.ratingMin == nil || place.rating >= filters.ratingMin!) &&
        (filters.ratingMax == nil || place.rating <= filters.ratingMax!) &&
        (filters.priceMin == nil || place.price >= filters.priceMin!) &&
        (filters.priceMax == nil || place.price <= filters.priceMax!) &&
        (filters.searchText.isEmpty || place.name.contains(filters.searchText))
    }
}

} Learn More: For more insights on SwiftUI and advanced filtering techniques, check out this SwiftUI Filtering Guide.

I hope this helps! Feel free to reach out snaptube pro if you have more questions.

Best regards,

   

Hacking with Swift is sponsored by try! Swift Tokyo.

SPONSORED Ready to dive into the world of Swift? try! Swift Tokyo is the premier iOS developer conference will be happened in April 9th-11th, where you can learn from industry experts, connect with fellow developers, and explore the latest in Swift and iOS development. Don’t miss out on this opportunity to level up your skills and be part of the Swift community!

Get your ticket here

Sponsor Hacking with Swift and reach the world's largest Swift community!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.