Turning Bluetooth off doesn't usually work as a good way to test monitoring. Enter and exit events only happen when the region's state (i.e., CLRegionState
) transitions from "outside" to "inside" (and vice versa). If you turn Bluetooth off, the state goes to "unknown"[1] (because how would the device know if you're out or in with Bluetooth disabled), and thus if you switch it back on, and it transitions to "outside" or "inside," it won't actually trigger an event by design.
You can test that by implementing the didDetermineState
method, in addition to didEnter
and didExit
. Start with the beacon turned off, confirm via didDetermineState
that the state is "outside." Turn Bluetooth off, turn the beacon on, turn Bluetooth on. You will see didDetermineState
with state "inside," but no didEnter
. (It works the same the other way around, i.e., if you start with the beacon turned on, and turn it off while the iPhone's Bluetooth is disabled. You will see didDetermineState
"outside," but no didExit
.)
Note: this test only works in the foreground. It looks like in the background, didDetermineState
is not enough for iOS to wake up the app to handle the event—it needs to be didEnter
or didExit
.
[1] A little clarification here as well. When you disable Bluetooth, there won't actually be an explicit call to didDetermineState
with CLRegionStateUnknown
. This is because I suspect that iOS stops delivering any beacon events when Bluetooth is off. How did I arrive at the conclusion that it really changes to "unknown" then? I added an NSTimer
that calls requestStateForRegion
(which in turn forces an asynchronous call to didDetermineState
) every second. When I turn Bluetooth off, didDetermineState
calls stop arriving. But as soon as I turn Bluetooth on, these calls resume, and the state is "unknown"—before it changes to "outside" or "inside" depending on the current state of the beacon. Again, per the note above, all of this is with the app in the foreground.
(Same mechanics actually apply when you start monitoring already in range of a beacon. Before you start monitoring, the state is "unknown." When you start monitoring, the state transitions to "inside" our "outside" (depending on whether the beacon is in range at the time when monitoring starts), but this does not trigger didEnter
or didExit
. Here too you can verify this with didDetermineState
.)