Search code examples
jsonswiftasynchronousibeaconalamofire

locationManager and data managing


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
}

Solution

  • 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.