I have a map with fixed annotations, the annotations change only if I filter the results with a function
I'd like to recalculate the region as user moves the map and show the FILTERED results that match that location (get new region coordinates, then call my getListingsFiltered function)
how can I get the region coordinates when the map changes? I have seen I can use region.center for the move without zoom and regin.span for zoom in/out) but I couldn't make it work.
I've seen also that other answers change region based on change of results, but in my case it's the contrary, I want to change results based on change of map location.
Map
Map(coordinateRegion: self.$region,annotationItems: model.listingsFZ!) { listing in
MapAnnotation(coordinate: CLLocationCoordinate2D(latitude: listing.latitude ?? 0, longitude: listing.longitude ?? 0)) {
NavigationLink {
ListingDetailView(listing: listing)
} label: {
PlaceAnnotationView(title: listing.priceShort ?? "")
}
}
}
.onDisappear {
model.clear()
}
Function
func getListingsFiltered(location: String, PriceMin: String, PriceMax: String, Bedrooms: Int) {
var listingsF = [ListingsZillow]() //new array instance of listing
var regionSearch = self.region
var lowestPrice = 0
var highestPrice = 1000000000
if PriceMin == "Any" {lowestPrice = 0} else {lowestPrice = Int(PriceMin) ?? 0}
if PriceMax == "Any" {highestPrice = 1000000000} else { highestPrice = Int(PriceMax) ?? 1000000000}
//append the ones that match
for listing in self.listingsZ! {
//no region selected
if regionSearch.center.latitude == 0 || regionSearch.center.longitude == 0 {
if listing.price! >= lowestPrice && listing.price! <= highestPrice {
**some code**
}
} else {
//there is a regionselected
if listing.latitude != nil {
let listingRegion = CLLocationCoordinate2D(latitude: listing.latitude, longitude: listing.longitude)
if self.checkRegion(location: regionSearch.center, contains: listingRegion, with: 1000){
//condition price
if listing.price! >= lowestPrice && listing.price! <= highestPrice {
//condition bedrooms
if listing.bedrooms! >= Bedrooms {
//condition location
var l = ListingsZillow()
l.address = listing.address!
l.bedrooms = listing.bedrooms
l.bathrooms = listing.bathrooms
l.price = listing.price
l.yearBuilt = listing.yearBuilt
l.longitude = listing.longitude
l.latitude = listing.latitude
l.homeStatus = listing.homeStatus
l.description = listing.description
l.livingArea = listing.livingArea
l.url = listing.url
l.photos = listing.photos
l.priceShort = listing.priceShort
listingsF.append(l)
}
}
}
}
}
}
DispatchQueue.main.async {
//self.listingsF = listingsF
self.listingsFZ = listingsF
self.filters = true
}
}
CodePudding user response:
It can be done with the span in the region.
extension CLLocationCoordinate2D{
///Check if the `coordinate` is within the `MKCoordinateRegion`
func isWithinRegion(region: MKCoordinateRegion) -> Bool{
var result = false
//Get the upper and lower bounds of the latitude and longitude
//center /- span/2
//divide by 2 because the center is half way through
let latUpper = region.center.latitude region.span.latitudeDelta/2
let latLower = region.center.latitude - region.span.latitudeDelta/2
let lonUpper = region.center.longitude region.span.longitudeDelta/2
let lonLower = region.center.longitude - region.span.longitudeDelta/2
//If the coordinate is within the latitude and the longitude
if self.latitude >= latLower && self.latitude <= latUpper{
if self.longitude >= lonLower && self.longitude <= lonUpper{
//It is within the region
result = true
}
}
return result
}
}
If you add the code above to your project you can use something like
listing.coordinate.isWithinRegion(region: regionSearch)
in your filter.
The function will return true if the coordinate is within the region
You can dynamically set the annotations by using a computed variable
///Returns the `visibleAnnotations` that are within the `region`
var visibleAnnotations: [ListingAnnotation]{
//Your filter code
model.listingsZ.filter({
$0.coordinate.isWithinRegion(region: region)
})
}
Or just hide the listings if the operation is time-consuming
NavigationLink{}
.opacity(listing.coordinate.isWithinRegion(region: vm.region) ? 1 : 0)
.animation(.easeIn(duration: 1), value: listing.coordinate.isWithinRegion(region: vm.region))


