app crashes when no iBeacon is detected - Swift iOS -
i working on app uses ibeacons cllocation , light blue bean ios sdks. if run app battery out of beacon app works well. if insert battery beacon app detects beacon , works well. problem when remove battery beacon ( or when no beacon detected or beacon out of range) app crashes , gives me following error,
fatal error: array index out of range.
i understand error coming cllocationmanagerdelegate method didrangebeacons, im not sure how prevent app crashing? code below,
func locationmanager(manager: cllocationmanager!, didrangebeacons beacons: [anyobject]!, inregion region: clbeaconregion!) { self.listbeans = beacons; nsnotificationcenter.defaultcenter().postnotificationname("updatebeacontableview", object: self.listbeans) if beacons.count == 0{ println("no beacons nearby") manager.stopupdatinglocation() manager.stopmonitoringforregion(lightblueregion) }else{ let knownbeacons = beacons.filter{$0.proximity != clproximity.unknown} // proximity = 0 let closestbeacon = knownbeacons[0] as! clbeacon if(closestbeacon.proximity == lastproximity || closestbeacon.proximity == clproximity.unknown) { return; } lastproximity = closestbeacon.proximity; if (knownbeacons.count > 0){ switch closestbeacon.proximity { case clproximity.far: println("you far away beacon") case clproximity.near: println("you near beacon") case clproximity.immediate: println("you in immediate proximity of beacon") case clproximity.unknown: println("the proximity of beacon unknown") } } else { println("no beacons nearby") } } } func locationmanager(manager: cllocationmanager!, didenterregion region: clregion!) { /* detected every 1 second */ println("region discovered") var enteredregion = true } func locationmanager(manager: cllocationmanager!, didexitregion region: clregion!) { var enteredregion = false } func locationmanager(manager: cllocationmanager!, diddeterminestate state: clregionstate, forregion region: clregion!) { switch state { case clregionstate.inside: /* in .inside case first notification displayed when user inside region , opens app. second notification shown when app in background , user enters region*/ if enteredregion == true{ message = "diddeterminestate = inside region" } sendlocalnotificationwithmessage(message) case clregionstate.outside: /* similar logic follows .outside case. should noted further beacons longer take signal propagate means may take few seconds notifications displayed when leave or enter region.*/ if enteredregion == false{ message = "diddeterminestate = outside region" } sendlocalnotificationwithmessage(message) case clregionstate.unknown: sendlocalnotificationwithmessage("diddeterminestate = unknown region") default: break; } } func beanmanagerdidupdatestate(beanmanager: ptdbeanmanager!) { switch beanmanager.state { case .unsupported: var unsupportedalert = uialertcontroller(title: "error", message: "this device unsupported.", preferredstyle: uialertcontrollerstyle.alert) unsupportedalert.addaction(uialertaction(title: "ok", style: uialertactionstyle.default, handler: nil)) self.presentviewcontroller(unsupportedalert, animated: true, completion: nil) case .poweredoff: var ppoweredoffalert = uialertcontroller(title: "error", message: "please turn on bluetooth.", preferredstyle: uialertcontrollerstyle.alert) ppoweredoffalert.addaction(uialertaction(title: "ok", style: uialertactionstyle.default, handler: nil)) self.presentviewcontroller(ppoweredoffalert, animated: true, completion: nil) case .poweredon: beanmanager.startscanningforbeans_error(nil); default: break } } func beanmanager(beanmanager: ptdbeanmanager!, diddiscoverbean bean: ptdbean!, error: nserror!) { self.beanname = bean.name string self.beanuuidnum = bean.identifier.description }
thanks
update:
i ended following code,
let knownbeacons:anyobject? = beacons.filter{$0.proximity != clproximity.unknown} // proximity = 0 if let knownbeacons_:anyobject = knownbeacons { if knownbeacons_.count == 0 { return } if let closestbeacon = knownbeacons_[0] as? clbeacon{ if(closestbeacon.proximity == lastproximity || closestbeacon.proximity == clproximity.unknown) { return; } lastproximity = closestbeacon.proximity; if (knownbeacons_.count > 0){ switch closestbeacon.proximity { case clproximity.far: println("you far away beacon") case clproximity.near: println("you near beacon") case clproximity.immediate: println("you in immediate proximity of beacon") case clproximity.unknown: println("the proximity of beacon unknown") } } else { println("no beacons nearby") } }else{ println("no beacons nearby") manager.stopupdatinglocation() manager.stopmonitoringforregion(lightblueregion) } }
if knownbeacons empty, code crash. before trying access knownbeacons[0], need check whether or not array empty. try wrapping more code in if (knownbeacons.count > 0)
block more safety, this.
let knownbeacons = beacons.filter{$0.proximity != clproximity.unknown} // proximity = 0 if (knownbeacons.count > 0){ let closestbeacon = knownbeacons[0] as! clbeacon if(closestbeacon.proximity == lastproximity || closestbeacon.proximity == clproximity.unknown) { return; } lastproximity = closestbeacon.proximity; switch closestbeacon.proximity { case clproximity.far: println("you far away beacon") case clproximity.near: println("you near beacon") case clproximity.immediate: println("you in immediate proximity of beacon") case clproximity.unknown: println("the proximity of beacon unknown") } }
Comments
Post a Comment