Search code examples
iosswiftmonitoringregion

How to monitor more than 20 regions?


I'm working on an app in which there are 66 annotations. These annotations are centers of regions and whenever user enters a region, a notification appears, but that works only for first 20 of them because there's a limited number on monitoring regoins. My problem is that I don't know how to monitor more than 20 regions. Could anyone help?


Solution

  • set currentLocation from your didUpdateLocations

    var currentLocation : CLLocation?{
        didSet{
            evaluateClosestRegions()
        }
    }
    
    var allRegions : [CLRegion] = [] // Fill all your regions
    

    Now calculate and find the closest regions to your current location and only track those.

    func evaluateClosestRegions() {
    
        var allDistance : [Double] = []
    
        //Calulate distance of each region's center to currentLocation
        for region in allRegions{
            let circularRegion = region as! CLCircularRegion
            let distance = currentLocation!.distance(from: CLLocation(latitude: circularRegion.center.latitude, longitude: circularRegion.center.longitude))
            allDistance.append(distance)
        }
        // a Array of Tuples
        let distanceOfEachRegionToCurrentLocation = zip(allRegions, allDistance)
    
        //sort and get 20 closest
        let twentyNearbyRegions = distanceOfEachRegionToCurrentLocation
            .sorted{ tuple1, tuple2 in return tuple1.1 < tuple2.1 }
            .prefix(20)
    
        // Remove all regions you were tracking before
        for region in locationManager.monitoredRegions{
            locationManager.stopMonitoring(for: region)
        }
    
        twentyNearbyRegions.forEach{
            locationManager.startMonitoring(for: $0.0)
        }
    
    }
    

    To avoid having the didSet called too many times, I suggest you set the distanceFilter appropriately (not too big so you would catch the region's callbacks too late and not too small so that you won't have redundant code running). Or as this answer suggests, just use startMonitoringSignificantLocationChanges to update your currentLocation