未检测到 iBeacon 时应用程序崩溃 - Swift iOS
app crashes when no iBeacon is detected - Swift iOS
我正在开发一个将 iBeacons 与 CLLocation 和浅蓝色 bean ios sdks 结合使用的应用程序。如果我 运行 该应用程序的电池已从信标中取出,则该应用程序运行良好。如果我随后将电池插入信标,应用程序会检测到信标并且运行良好。问题是当我从信标中取出电池时(或者当没有检测到信标或信标超出范围时)应用程序崩溃并给我以下错误,
致命错误:数组索引超出范围。
我知道这个错误来自 CLLocationManagerDelegate 方法 didRangeBeacons,但我不确定如何防止我的应用程序崩溃?我的代码在下面,
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{[=12=].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 are far away from the beacon")
case CLProximity.Near:
println("You are near the beacon")
case CLProximity.Immediate:
println("You are in the immediate proximity of the beacon")
case CLProximity.Unknown:
println("The proximity of the beacon is Unknown")
}
} else {
println("No beacons are nearby")
}
}
}
func locationManager(manager: CLLocationManager!, didEnterRegion region: CLRegion!) {
/* detected every one 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 the .Inside case first notification is
displayed when the user is inside the region
and opens an app.
Second notification is shown when the app is in background
and the user enters the region*/
if enteredRegion == true{
message = "didDetermineState = INSIDE a region"
}
sendLocalNotificationWithMessage(message)
case CLRegionState.Outside:
/* Similar logic follows the .Outside case. It should be noted that the further you are from the beacons the longer it will take for the signal to propagate which means it may take few seconds for the notifications to be displayed when you leave or enter the region.*/
if enteredRegion == false{
message = "didDetermineState = OUTSIDE a 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 is 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 as String
self.beanUUIDNum = bean.identifier.description
}
谢谢
更新:
我得到了以下代码,
let knownBeacons:AnyObject? = beacons.filter{[=13=].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 are far away from the beacon")
case CLProximity.Near:
println("You are near the beacon")
case CLProximity.Immediate:
println("You are in the immediate proximity of the beacon")
case CLProximity.Unknown:
println("The proximity of the beacon is Unknown")
}
} else {
println("No beacons are nearby")
}
}else{
println("no beacons nearby")
manager.stopUpdatingLocation()
manager.stopMonitoringForRegion(lightBlueRegion)
}
}
这里是红旗:
let closestBeacon = knownBeacons[0] as! CLBeacon
即使数组可能为空(并且索引 0 处的对象将 nil/you 超出数组范围),您仍在强制展开 knownBeacons[0]
。考虑使用 if let
:
if let closestBeacon = knownBeacons[0] as! CLBeacon {
if(closestBeacon.proximity == lastProximity ||
closestBeacon.proximity == CLProximity.Unknown) {
return;
}
} else {
// handle no beacons case
}
如果 knownBeacons 为空,您的代码将崩溃。在尝试访问 knownBeacons[0] 之前,您需要检查数组是否为空。尝试在 if (knownBeacons.count > 0)
块中包装更多代码以提高安全性,就像这样。
let knownBeacons = beacons.filter{[=10=].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 are far away from the beacon")
case CLProximity.Near:
println("You are near the beacon")
case CLProximity.Immediate:
println("You are in the immediate proximity of the beacon")
case CLProximity.Unknown:
println("The proximity of the beacon is Unknown")
}
}
我正在开发一个将 iBeacons 与 CLLocation 和浅蓝色 bean ios sdks 结合使用的应用程序。如果我 运行 该应用程序的电池已从信标中取出,则该应用程序运行良好。如果我随后将电池插入信标,应用程序会检测到信标并且运行良好。问题是当我从信标中取出电池时(或者当没有检测到信标或信标超出范围时)应用程序崩溃并给我以下错误,
致命错误:数组索引超出范围。
我知道这个错误来自 CLLocationManagerDelegate 方法 didRangeBeacons,但我不确定如何防止我的应用程序崩溃?我的代码在下面,
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{[=12=].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 are far away from the beacon")
case CLProximity.Near:
println("You are near the beacon")
case CLProximity.Immediate:
println("You are in the immediate proximity of the beacon")
case CLProximity.Unknown:
println("The proximity of the beacon is Unknown")
}
} else {
println("No beacons are nearby")
}
}
}
func locationManager(manager: CLLocationManager!, didEnterRegion region: CLRegion!) {
/* detected every one 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 the .Inside case first notification is
displayed when the user is inside the region
and opens an app.
Second notification is shown when the app is in background
and the user enters the region*/
if enteredRegion == true{
message = "didDetermineState = INSIDE a region"
}
sendLocalNotificationWithMessage(message)
case CLRegionState.Outside:
/* Similar logic follows the .Outside case. It should be noted that the further you are from the beacons the longer it will take for the signal to propagate which means it may take few seconds for the notifications to be displayed when you leave or enter the region.*/
if enteredRegion == false{
message = "didDetermineState = OUTSIDE a 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 is 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 as String
self.beanUUIDNum = bean.identifier.description
}
谢谢
更新:
我得到了以下代码,
let knownBeacons:AnyObject? = beacons.filter{[=13=].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 are far away from the beacon")
case CLProximity.Near:
println("You are near the beacon")
case CLProximity.Immediate:
println("You are in the immediate proximity of the beacon")
case CLProximity.Unknown:
println("The proximity of the beacon is Unknown")
}
} else {
println("No beacons are nearby")
}
}else{
println("no beacons nearby")
manager.stopUpdatingLocation()
manager.stopMonitoringForRegion(lightBlueRegion)
}
}
这里是红旗:
let closestBeacon = knownBeacons[0] as! CLBeacon
即使数组可能为空(并且索引 0 处的对象将 nil/you 超出数组范围),您仍在强制展开 knownBeacons[0]
。考虑使用 if let
:
if let closestBeacon = knownBeacons[0] as! CLBeacon {
if(closestBeacon.proximity == lastProximity ||
closestBeacon.proximity == CLProximity.Unknown) {
return;
}
} else {
// handle no beacons case
}
如果 knownBeacons 为空,您的代码将崩溃。在尝试访问 knownBeacons[0] 之前,您需要检查数组是否为空。尝试在 if (knownBeacons.count > 0)
块中包装更多代码以提高安全性,就像这样。
let knownBeacons = beacons.filter{[=10=].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 are far away from the beacon")
case CLProximity.Near:
println("You are near the beacon")
case CLProximity.Immediate:
println("You are in the immediate proximity of the beacon")
case CLProximity.Unknown:
println("The proximity of the beacon is Unknown")
}
}