简体   繁体   中英

Use NSTimer for better validation of beacon

I have a program in SWIFT, that detects when a beacon or multiple beacons are out of range and based on that it will perform something like saving some data into database and etc. Everything works well, however I do get lots of false positive in a way that "didExitRegion" getting fired and few secs later "didEnterRegion" getting fired while I haven't been moved or etc.
I know this has lot to do with the tuning of the beacons and their qualities, but at this time I have come up with an alternative solution.
So I decided to use NSTimer to see if I am really off range or is it just a false positive that I am getting? so when didExitRegion is getting fired, I start a NSTimer for 60 secs. If the 60 secs is up and didEnterRegion didn't get fire, then I know I am really out of range and perform whatever data saving I need to do. Otherwise if didEnterRegion is called within that 60 secs, then I'll assume it was a false positive and invalidate the nstimer and not doing anything.

Everything works well as long as I am working with one beacon. The problem I have with timer is when multiple beacons go out of range. lets say first beacon is out of range, so didExitRegion is getting fire and start the NSTimer Let say 20 secs later second beacon is off range and again didExitRegion is getting fired and that one starts the NSTimer again. Now my NStimer is all out of synch and at that time, things are not working correct and the NSTimer continuously start itself when 60 secs is up and etc.

So my question is what is the work around this solution? How can I keep my nstimer in synch when is called again before is invalidated? Is there a better way to this solution? Again, I know a better quality beacons can help, but that is not an option for me at this time.

One solution is to keep a dictionary like this:

var pendingExits = Dictionary<CLBeaconRegion,NSDate>()

Each time you get a didExitRegion call:

  • Only start the NSTimer if the dictionary is empty -- otherwise, assume the timer is already running.

  • Add the region to the dictionary along with a new NSDate() to set the timestamp of when it was added.

When you get a didEnterRegion callback:

  • Look for the region in the dictionary. If it is there, remove it.

When the timer goes off:

  • Look for any entry with a timestamp 60 seconds or more old. For this, remove the region from the dictionary and fire your custom exit logic.

Find the newest remaining timestamp (if any) in the dictionary. Start the timer to go off at that time plus 60 seconds.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM