0

My question is essentially the same as the one here:
iOS Geofence, how to handle when inside region when monitoring starts?

I need a Swift 3 solution.

I'm using the excellent raywenderlich tutorial on Geofencing and it's working in my project with very little customization. My app responds perfectly when crossing geofence boundaries.

But I need to determine at app startup if the user is already inside a geofence or not.

I'm assuming I need to use

locationManager.requestState(for region: CLRegion)

in my appDelegate.

The piece I'm missing is how to load my geofenced region as a CLRegion so that I can use it to call that function at startup.

Here's something I've tried that does not work.

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
...   //  There's some other stuff
   locationManager.delegate = self
   locationManager.requestAlwaysAuthorization()        
   loadAllGeotifications()  //  There will be only one !!
   let homeRegion = region(withGeotification: geotifications[1]) as! CLRegion
    locationManager.requestState(for: homeRegion)
    return true
}

func loadAllGeotifications() {
    geotifications = []
    guard let savedItems = UserDefaults.standard.array(forKey: PreferencesKeys.savedItems) else { return }
    for savedItem in savedItems {
        guard let geotification = NSKeyedUnarchiver.unarchiveObject(with: savedItem as! Data) as? Geotification else { continue }
            geotifications.append(geotification)
    }
}


func region(withGeotification geotification: Geotification) -> CLCircularRegion {
    let region = CLCircularRegion(center: geotification.coordinate, radius: geotification.radius, identifier: geotification.identifier)
    return region
   }
}

func locationManager(manager: CLLocationManager, didDetermineState state: CLRegionState, forRegion region: CLRegion) {
    let defaults: UserDefaults = UserDefaults.standard
    switch state {
    case .inside:
        defaults.set(true, forKey: "atHome")
    case .outside:
        defaults.set(false, forKey: "atHome")
    default:
        defaults.set(true, forKey: "atHome")   //  Assume user is at home unless/until determined otherwise
    }
}

The didDetermineState never comes back. Same problem whether the CLCircularRegion is recast to CLRegion or not - no difference.

Wayne Henderson
  • 237
  • 3
  • 9

1 Answers1

1

I solved it!

Here's the replacement code that did the trick:

func locationManager(_ manager: CLLocationManager, didDetermineState state: CLRegionState, for region: CLRegion) {
... }

Note the addition of "_ " preceding "manager".

My "atHome" flag is now set properly when the app starts up.

The recasting as ULRegion is OK but is not necessary.

let homeRegion = region(withGeotification: geotifications[1])

...works fine

Wayne Henderson
  • 237
  • 3
  • 9