如何在地图移动时以编程方式获取新区域,以便我可以刷新注释? (swiftui)

how to programmatically get new region as Map moves so I can refresh annotations? (swiftui)

我有一个带有固定注释的地图,只有当我使用函数过滤结果时注释才会改变

我想在用户移动地图时重新计算区域并显示匹配该位置的筛选结果(获取新的区域坐标,然后调用我的 getListingsFiltered 函数)

当地图改变时如何获取区域坐标?我已经看到我可以使用 region.center 进行不缩放的移动和 regin.span 进行缩放zoom in/out) 但我无法让它工作。

我还看到其他答案会根据结果的变化来改变区域,但在我的情况下恰恰相反,我想根据地图位置的变化来改变结果。

我的地图

想要的结果(zillow)

地图

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()
                }

函数

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

可以用 region 中的 span 来完成。

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

如果您将上面的代码添加到您的项目中,您可以使用类似

的东西
listing.coordinate.isWithinRegion(region: regionSearch)

在你的过滤器中。

如果坐标在region

范围内,函数将returntrue

您可以使用计算变量动态设置注释

///Returns the  `visibleAnnotations` that are within the `region`
var visibleAnnotations: [ListingAnnotation]{
    //Your filter code 
    model.listingsZ.filter({
        [=12=].coordinate.isWithinRegion(region: region)
    })
}

或者如果操作是 time-consuming

则隐藏列表
NavigationLink{}
    .opacity(listing.coordinate.isWithinRegion(region: vm.region) ? 1 : 0)
    .animation(.easeIn(duration: 1), value: listing.coordinate.isWithinRegion(region: vm.region))