didEnterRegion and didExitRegion are not being called

hello everyone,

im building my first app with estimate beacons and im following the tutorial on the page about Background monitoring.

the problem is that i completed the tutorial and it doesn’t work. The methods didEnterRegion and didExitRegion are not being called. The only method that are being called is didStartMonitoringForRegion.

i added the NSLocationAlwaysUsageDescription in the info.plist.

its not necessary to put here the code because its the same as the tutorial (http://developer.estimote.com/ibeacon/tutorial/part-1-setting-up/)

can someone help me?

thx in advance.

We’ll figure it out, no worries (:

Have you changed to UUID, major, and minor value from the one provided in the tutorial to that of your own beacon? Can you double-check if the Location Services is set to “always” in Settings for your app? Are you testing with flip-to-sleep, like the tutorial recommends?

well im using the standard uuid ( like in the tutorial) with the minor and major of my beacon.

i added the NSLocationAlwaysUsageDescription to my info.plist and when i start the app it asks for permission to use the location.

the only thing that i didn’t test was the flip-to-sleep that i will do now.

and im using the didDetermineState func of beacon manager and this func its not called either

i can’t use the flip-to-sleep because the beacons are not mine and i don’t have access to their account enable the option.

mean while i went way with the beacon and came back to the device and neither of my methods was called (didEnterRegion, didDetermineState, didExitRegion)

this might be a simple thing but im not getting it :smile:

Is didDetermineState being called after you start monitoring? It should be, with the initial state of the beacon. If it’s not, then there’s something wrong with your monitoring setup. Can you share some code here?

this is my app delegate file

import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, ESTBeaconManagerDelegate {

    var window: UIWindow?
    
    // 2. Add a property to hold the beacon manager and instantiate it
    let beaconManager = ESTBeaconManager()


    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
        // this is where we left off:
        self.beaconManager.delegate = self
        // add this below:
        self.beaconManager.requestAlwaysAuthorization()
        
        self.beaconManager.startMonitoringForRegion(CLBeaconRegion(
            proximityUUID: NSUUID(UUIDString: "B9407F30-F5F8-466E-AFF9-25556B57FE6D")!,
            identifier: "monitored region"))
        
        let notifTypes: UIUserNotificationType = [.Alert, .Badge, .Sound]
        let notifSettings = UIUserNotificationSettings(forTypes: notifTypes, categories: nil)
        UIApplication.sharedApplication().registerUserNotificationSettings(notifSettings)

        
        
        
        return true
    }

    func applicationWillResignActive(application: UIApplication) {
        // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
        // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
    }

    func applicationDidEnterBackground(application: UIApplication) {
        // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
        // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
    }

    func applicationWillEnterForeground(application: UIApplication) {
        // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
    }

    func applicationDidBecomeActive(application: UIApplication) {
        // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
    }

    func applicationWillTerminate(application: UIApplication) {
        // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
    }
    func beaconManager(manager: AnyObject!, didEnterRegion region: CLBeaconRegion!) {
        let notification = UILocalNotification()
        notification.alertBody =
            "didEnterRegion"
        UIApplication.sharedApplication().presentLocalNotificationNow(notification)
    }
    
    func beaconManager(manager: AnyObject!, didDetermineState state: CLRegionState, forRegion region: CLBeaconRegion!) {
        let notification = UILocalNotification()
        notification.alertBody =
            "didDetermineState"
        UIApplication.sharedApplication().presentLocalNotificationNow(notification)
    }
    
    func beaconManager(manager: AnyObject!, monitoringDidFailForRegion region: CLBeaconRegion!, withError error: NSError!) {
        let notification = UILocalNotification()
        notification.alertBody = "monitoringDidFailForRegion"
        UIApplication.sharedApplication().presentLocalNotificationNow(notification)
    }
    
    func beaconManager(manager: AnyObject!, didExitRegion region: CLBeaconRegion!) {
        let notification = UILocalNotification()
        notification.alertBody =
            "didExitRegion"
        UIApplication.sharedApplication().presentLocalNotificationNow(notification)
    }
    
    func beaconManager(manager: AnyObject!, didStartMonitoringForRegion region: CLBeaconRegion!) {
        let notification = UILocalNotification()
        notification.alertBody =
            "didStartMonitoringForRegion"
        UIApplication.sharedApplication().presentLocalNotificationNow(notification)
    }
    
    func beaconManager(manager: AnyObject!, didFailWithError error: NSError!) {
        let notification = UILocalNotification()
        notification.alertBody =
            "didFailWithError"
        UIApplication.sharedApplication().presentLocalNotificationNow(notification)
    }


}

and my didDetermineState its not being called. the only method that are being called is didStartMonitoringForRegion

did u had time to check my code?

The code looks good, I can’t yet say why the other callbacks don’t work. Can you try to go to cloud.estimote.com, the “Apps” section, and add a new app via the “Notification” template, and check if that works?

its not working eitheir, im using xcode 7 , could be beacuase i need to disable the bitcode option to compile?

I got the same problem, ObjC and Swift. didEnterRegion and didExitRegion are not being called.

are u using xcode 7?

Yep! Xcode 7, but when I use Xcode 6, they are not being called too. I don’t understand why? But ranging still work well

@phongnguyendev, if ranging works but monitoring doesn’t, can you double check if you app has the “always” authorization to access location services, instead of the “when in use” authorization? Can you implement the didStartMonitoring, monitoringDidFail, and didDetermineState methods and see if these get called?

@phongnguyendev & @Ricardo_Costa, what iOS devices do you guys use? What iOS version? Can you try calling requestStateForRegion—it should force a call to the didDetermineState, does it say “outside” or “unknown” then?

well @heypiotr. I’m using “always” like this [self.estBeaconManager requestAlwaysAuthorization];
And I’m testing with iPad 4 Gen iOS 8.4, and with requestStateForRegion, it return CLRegionStateInside. It’s fine with requestState right?

im using ipad mini with iOS 8.1 and when i call requestStateForRegion it enters in didDetermineState but the info that i get in the state variable is CLRegionState

One important thing to keep in mind, I’m not sure if you guys are aware of this behavior—if you do, then sorry for over-explaining (:

Enter and exit events are only triggered when the state changes, i.e., goes from inside to outside and vice versa. If you start monitoring with the beacon already in range, it won’t trigger an immediate enter. Same for exit—if you start monitoring and the beacon is out of range, there won’t be an immediate exit.

Furthermore, exit event has an internal delay of 30 seconds—so you need to leave the range of the beacon for at least 30 seconds in order for it to trigger.

I’ll try to illustrate this with an example:

  1. Let’s assume we’re starting with the beacon in range of the device.
  2. You call startMonitoring.
  3. Monitoring starts, and the state of the beacon region is determined to be “inside.” There should be a call to didDetermineState with this initial state, but there won’t be a call to didEnter.
  4. You move out of range of the beacon. As soon as you’re out, the clock starts ticking.
  5. When the clocks reaches 30 seconds, the state of the beacon region will change to “outside.” There will be a call to didDetermineState. Also, since the state changed from “inside” to “outside,” there will be a call to didExit.
  6. Now you move back in range. The state changes to “inside” again. There will be a call to didDetermineState. And again, since the state changed from “outside” to “inside,” there now will be a call to didEnter.

Last but not least, for some devices, and in some special cases, it may actually take up to 15 minutes for iOS to acknowledge the state change. We know this to be the case for iPhone 4S, and I’m not sure about iPads. Newer iPhones (5, 5S, 6, etc.) usually respond immediately. Any chance you have some alternative iOS device at hand to test?

Well, thank I understand its mechanism. I shall give a try. So that because of state is “outside” so it doesn’t call didEnterRegion or didExitRegion. Thank you very much for your help, very kind of u @heypiotr.

i understand that but my didDetermineState don’t have the “inside” or “outside” value. when it triggers (with the use of requestStateForRegion) the state variable have the value CLRegionState

In Swift, you need to use state.rawValue. 0 = unknown, 1 = inside, 2 = outside.

ok the value is 0 so its unknown, and i have the beacon close to my ipad