Source: https://developers.woosmap.com/products/geofencing-sdk/ios-sdk/guides/monitor-pois/

> For clean Markdown of any page, append `.md` to the page URL.

> For a complete documentation index, see https://developers.woosmap.com/llms.txt

# Monitor places with custom geofence



##  Create and monitor custom Geofences
  
Use region monitoring to determine when the user enters or leaves a geographic region.

Region monitoring (also known as geofencing) combines awareness of the user's current location with awareness of the
user's proximity to locations that may be of interest. This region is a way for your app to be alerted when the user
enters or exits a geographical region. To mark a location of interest, you specify its latitude and longitude. To adjust
the proximity for the location, you add a radius. The latitude, longitude, and radius define a Geofence, creating a
circular area, or isochrone geofence, around the location of interest. Find more details about Geofences in
the [Geofencing documentation](/products/geofencing-sdk/geofencing/)

### Set up for Geofence monitoring

The first step in requesting Geofence monitoring is to set `regionDelegate`, this should be done as early as possible in your didFinishLaunchingWithOptions App Delegate.

```swift
let dataLocation = DataLocation()
let dataPOI = DataPOI()
let dataRegion = DataRegion()

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        
        // Set delegate of protocol Location, POI and Distance
        WoosmapGeofenceManager.shared.getLocationService().locationServiceDelegate = dataLocation
        WoosmapGeofenceManager.shared.getLocationService().regionDelegate = dataRegion
}
``` 

### Region Service Delegate
In your class delegate, retrieve Region data : 
```swift
public class DataRegion:RegionsServiceDelegate  {
    
    public init() {}
    
    public func updateRegions(regions: Set<CLRegion>) {
        NotificationCenter.default.post(name: .updateRegions, object: self,userInfo: ["Regions": regions])
    }
    
    public func didEnterPOIRegion(POIregion: Region) {
        NotificationCenter.default.post(name: .didEventPOIRegion, object: self,userInfo: ["Region": POIregion])
    }
    
    public func didExitPOIRegion(POIregion: Region) {
        NotificationCenter.default.post(name: .didEventPOIRegion, object: self,userInfo: ["Region": POIregion])
    }
    
    public func workZOIEnter(classifiedRegion: Region) {
        NotificationCenter.default.post(name: .didEventPOIRegion, object: self, userInfo: ["Region": classifiedRegion])
    }
    
    public func homeZOIEnter(classifiedRegion: Region) {
        NotificationCenter.default.post(name: .didEventPOIRegion, object: self, userInfo: ["Region": classifiedRegion])
    }
    
    public func readRegions()-> [Region] {
        return Regions.getAll()
    }
    
    public func eraseRegions() {
        Regions.deleteAll()
    }
}
```

Whenever the user crosses the boundary of one of your app's registered regions, the system notifies your app.

Boundary crossing notifications are delivered to your region delegate object. Specifically, `(_:didEnterRegion:)` or `(_:didExitRegion:)` methods.

On the object `Region`, there are an boolean `didEnter` that indicate if you enter or exit of the region. You have another boolean `fromPositionDetection` to know if the detection was launch by the position detection or by the system detection. The system only manages circle geofence so ignore for type isochrone.

When determining whether a boundary crossing happened, the system waits to be sure before sending the notification. Specifically, the user must travel a minimum distance over the boundary and remain on the same side of the boundary for at least 20 seconds. These conditions help eliminate spurious calls to your delegate object’s methods.

<p align="center">
  <img alt="Exit region event" src="https://github.com/woosmap/woosmap-geofencing-ios-sdk/raw/master/assets/exitregion.png" width="50%">
</p>

Regions have an associated identifier, which this method uses to look up information related to the region and perform the associated action.

### Create a custom region

A region is an area centered on a geographic coordinate. There are two types of region, `circle` and `isochrone`. You can define one using a `CLLocationCoordinate2D` object. The radius of the region object defines its boundary. The radius in meters for type circle, a number higher than 100 is recommended. The travel duration in seconds for type isochrone, a number higher than 180 seconds is recommended. You define the regions you want to monitor and register them with the system by calling the `addRegion(center: CLLocationCoordinate2D, radius: Int, type: String)` method of `WoosmapGeofenceManager.shared.locationService`. The system monitors your regions until you explicitly ask it to stop or until the device reboots.

```swift
let (regionIsCreated, identifier) = WoosmapGeofenceManager.shared.locationService.addRegion(
    identifier: region_identifer, 
    center: coordinate, 
    radius: 100, // 100 meters 
    type: "circle"
)
```

This method returns the state of creation (true or false) and the identifier of the region created by the SDK. If this method returns false, the limit of numbers of regions monitored has been exceed. Indeed, regions are shared resources that rely on specific hardware capabilities. To ensure that all apps can participate in region monitoring, Core Location prevents any single app from monitoring more than 20 circular regions simultaneously. The SDK creates 13 circular regions to monitor the user location, so you have only 7 slot circular regions available.

 To work around this limitation, use Woosmap Search API and load these places as Woosmap assets. More information in the dedicated documentation page: [Monitor Woosmap assets](/products/geofencing-sdk/ios-sdk/guides/monitor-woosmap-assets/).
 
 If you add a region with the same identifier than old region, the old region will be removed from the monitoring and replace by the new one.
 
#### Create a custom isochrone region

To monitor an isochrone geofence, the Geofencing SDK regularly request [Woosmap Distance API](/products/distance-api/features/isochrone/):

Enable/disable traffic data with the `setDistanceWithTraffic(trafficMode: Bool)` method:

```swift
WoosmapGeofenceManager.shared.setDistanceWithTraffic(trafficMode: false)
```

Remember to define a Woosmap key before create isochrone geofences.

```swift
WoosmapGeofenceManager.shared.setWoosmapAPIKey(key: WoosmapKey)

let (regionIsCreated, identifier) = WoosmapGeofenceManager.shared.locationService.addRegion(
      identifier: region_identifer, 
      center: coordinate, 
      radius: 180, // 180 seconds -> 3 minutes 
      type: "isochrone"
)
```

At any time, you can also modify the travel mode related to the user. Three travel mode are available: `driving`, `walking` and `cycling`. 
Use the following method to modify the travel mode:

```swift
WoosmapGeofenceManager.shared.setDistanceAPIMode(mode: DistanceMode.driving)
```

### Remove regions

To remove all regions created, you can use this method  : 
```swift
WoosmapGeofenceManager.shared.locationService.removeRegions(type: RegionType.none)
```

To remove only custom regions created and not remove POI regions, you can use this method  : 
```swift
WoosmapGeofenceManager.shared.locationService.removeRegions(type: RegionType.custom)
```
