I'm writing an application to scan iBeacon devices and fetch from database data related to beacons using Alamofire and SwiftyJSON. My problem is devices are scanned every second and I want to keep actual tableview of beacons in range. For example when I lose couple of beacons in the same time I get array index out of boundary error.
func locationManager(locationManager: KTKLocationManager!, didRangeBeacons beacons: [AnyObject]!) {
let knownBeacons = beacons.filter{ $0.proximity != CLProximity.Unknown }
let group = dispatch_group_create()
dispatch_group_enter(group)
deleteFromFoundBeacons(knownBeacons)
dispatch_group_leave(group)
dispatch_group_notify(group, dispatch_get_main_queue(), {
if (knownBeacons.count > 0) {
self.addToFoundBeacons(knownBeacons)
}
})
tableView.reloadData()
}
func addToFoundBeacons(knownBeacons: [AnyObject]!) {
for i in 0..<knownBeacons.count {
var isOnList = false
let foundBeacon = knownBeacons[i] as! CLBeacon
for j in 0..<Equipments.count {
if (knownBeacons[i].minor == Equipments[j].minor) {
isOnList = true
}
}
if (isOnList == false) {
httpProtocol.makeGetRequestForEquipment(foundBeacon.minor) { equipment in
if let equipment = equipment {
self.Equipments.append(equipment)
}
}
}
}
}
func deleteFromFoundBeacons(knownBeacons: [AnyObject]!) {
for i in 0..<Equipments.count {
var isToDelete = true
for j in 0..<knownBeacons.count {
if (knownBeacons[j].minor == Equipments[i].minor) {
isToDelete = false
}
}
if (isToDelete) {
Equipments.removeAtIndex(i)
}
}
}
Adding new beacons to Equipments (and tableview) works correctly, but when any of beacons leave scanning range then error shows up. My question is how to make beacon management independend from locationManager function which is called every second?
These are methods for tableView:
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return Equipments.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("EquipmentTableViewCell", forIndexPath: indexPath) as! EquipmentTableViewCell
let equipment = Equipments[indexPath.row]
cell.equipmentLabel.text = equipment.name
cell.equipmentPhoto.image = equipment.photo
return cell
}
The problem was solved by adding another if statement to check whether i < Equipments.count
in deleteFromFoundBeacons
before every iteration of the main loop. Thanks to it I also got rid off dispatch section in locationManager
. I also changed tableView.reloadData()
to beginUpdates() - endUpdates()
sections in order to manage table dynamically in every scan.