I ran into this issue as well. I was having a beacon from across the room flickering into domination over a beacon that was 3 inches away and this was a new set of beacons.
And here is why…
[CLBeacon (uuid:<__NSConcreteUUID 0x14c69e490> B9407F30-F5F8-466E-AFF9-25556B57FE6D, major:13719, minor:65410, proximity:3 +/- 2.59m, rssi:-83),
CLBeacon (uuid:<__NSConcreteUUID 0x14c6399b0> B9407F30-F5F8-466E-AFF9-25556B57FE6D, major:3720, minor:63371, proximity:3 +/- 5.80m, rssi:-90),
CLBeacon (uuid:<__NSConcreteUUID 0x14c69db20> B9407F30-F5F8-466E-AFF9-25556B57FE6D, major:25615, minor:47301, proximity:0 +/- -1.00m, rssi:0)]
You might have to scroll right but the closest beacon went to 0 rssi which put it on the bottom of the pile.
I was using the prefab “proximity content” app to see how this all worked and while there is a “firstEventSent” check that forces it to happen twice in a row, these events it would occasionally last for a couple iterations which would take it beyond its “firstEvenSent” check. And it seemed to be even worse as I walked around.
So for iOS Swift in “NearestBeaconManager.swift” I replaced the “firstEventSent” check with a check on a counter. So the number 1 closest, if it changed, would have to persist more than 3 times in a row to change the app. Of course the sacrifice is having to wait a few seconds for it to figure this out because iOS only seems to refresh its delegate every second or so.
func beaconManager(manager: AnyObject, didRangeBeacons beacons: [CLBeacon], inRegion region: CLBeaconRegion) { print("NearestBeaconManager : beaconManager")
let nearestBeacon = beacons.first
// These just check to see what is being passed in.
print("PASSED BEACONS")
print(beacons)
if nearestBeacon?.beaconID != self.nearestBeaconID{
if self.countEventSent > 3 {
//If it has changed for more than 3 itterations, send that change up the stack!
self.nearestBeaconID = nearestBeacon?.beaconID
self.delegate?.nearestBeaconManager(self, didUpdateNearestBeaconID: self.nearestBeaconID)
// Reset that count now that we have a new king beacon!
self.countEventSent = 1
print("NEW LOCATION")
print(nearestBeacon?.beaconID)
} else {
//Increment the count to hold off and make sure it is a true change.
self.countEventSent++
print("LOCATION CHANGED??")
}
//self.firstEventSent = true
} else {
// we don't want countEventSent to increment just because it had a previous hickup, so reset if the old and new are identical.
self.countEventSent = 1
}
}
While there is a little bit of lag, you can reduce the number of checks from 3 to 2 if you notice it doesn’t happen often.
Hope this helps.