我在同时监视多个信标时遇到问题。我的代码只能使用一个,但是我似乎无法弄清楚如何监视多个信标并更新UILabel。
当我打开信标时,所有这些信标都会受到监视和识别,但是我的手机无法在视图中显示正确的标签。除非它是函数(Estimote)中的最后一个信标,否则它会在distanceReading.text中不断显示“ UNKOWN”。
我还遇到其他一些更新其信标名称的问题。我不确定如何调用信标标识符,这将是理想的方式(类似于beacon.identifier)。我尝试创建另一个变量并通过每次信标扫描来更新名称,但是它只扫描最后一个变量,并且没有变化。我希望它在检测到它时会对其进行扫描,从而允许我在检测到新信标时更改变量。
我尝试将所有信标放入一个startScanning()函数中,为每个唯一的UUID提供变量,并对每个单独的信标使用locationManager.startMonitoring()和locationManager.startRangingBeacon()。然后,我尝试使用每个UUID,主要,次要和标识符的参数创建一个startScanning()函数,然后为每个信标调用该函数。
class ViewController: UIViewController, CLLocationManagerDelegate {
@IBOutlet var distanceReading: UILabel!
@IBOutlet var nameLabel: UILabel!
var locationManager: CLLocationManager?
var beaconDict: [String: String]?
var labelName: String?
override func viewDidLoad() {
super.viewDidLoad()
locationManager = CLLocationManager()
locationManager?.delegate = self
locationManager?.requestAlwaysAuthorization()
alertShown = false
view.backgroundColor = .gray // default is in "unknown mode"
}
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
if status == .authorizedAlways {
// Can we monitor beacons or not?
if CLLocationManager.isMonitoringAvailable(for: CLBeaconRegion.self) {
// Can we detect the distance of a beacon?
if CLLocationManager.isRangingAvailable() {
startScanning(uuid: UUID(uuidString: "5A4BCFCE-174E-4BAC-A814-092E77F6B7E5")!, major: 123, minor: 456, identifier: "Apple Beacon", name: "Apple")
startScanning(uuid: UUID(uuidString: "2F234454-CF6D-4A0F-ADF2-F4911BA9FFA6")!, major: 123, minor: 456, identifier: "Radius Beacon", name: "Radius")
startScanning(uuid: UUID(uuidString: "5AFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF")!, major: 123, minor: 456, identifier: "Red Bear Beacon", name: "Red Bear")
startScanning(uuid: UUID(uuidString: "B9407F30-F5F8-466E-AFF9-25556B57FE6D")!, major: 123, minor: 456, identifier: "Estimote", name: "Estimote")
}
}
}
}
func startScanning(uuid: UUID, major: UInt16, minor: UInt16, identifier: String, name: String) {
let uuidApple = uuid
let beaconRegion1 = CLBeaconRegion(proximityUUID: uuidApple, major: major, minor: minor, identifier: identifier)
locationManager?.startMonitoring(for: beaconRegion1)
locationManager?.startRangingBeacons(in: beaconRegion1)
labelName = name
}
func update(distance: CLProximity) {
UIView.animate(withDuration: 1) {
switch distance {
case .far:
self.view.backgroundColor = .blue
self.distanceReading.text = "FAR"
case .near:
self.view.backgroundColor = .orange
self.distanceReading.text = "NEAR"
case .immediate:
self.view.backgroundColor = .red
self.distanceReading.text = "RIGHT HERE"
default:
self.view.backgroundColor = .gray
self.distanceReading.text = "UNKNOWN"
}
}
}
func locationManager(_ manager: CLLocationManager, didRangeBeacons beacons: [CLBeacon], in region: CLBeaconRegion) {
if let beacon = beacons.first {
nameLabel.text = labelName
update(distance: beacon.proximity)
} else {
update(distance: .unknown)
}
}
我希望每次检测到新的信标时,我的标签都会相应更改。这按称为LAST的信标预期工作,但不适用于前三个。颜色改变了,但是标签拒绝改变。我还想找出一种方法来调用在CLBeaconRegion中设置的信标的标识符。
答案 0 :(得分:2)
尝试像for beacon in beacons
那样遍历所有远程信标,而不是像beacons.first
那样只处理数组中的第一个信标。
答案 1 :(得分:1)
您的信标名称问题是labelName
是单个字符串,并且您在startScanning
中设置了它的值。每次调用startScanning
时,您都会覆盖labelName
的先前值。自从您最后一次致电startScanning
以来,您就提供了 Estimote 这个名称,该名称将始终在nameLabel
中显示。
您有一个beaconDict
属性,它表明您可能已经在考虑这一点,但是没有继续进行。
我要做的是创建一个Beacon
结构来保存信标的所有属性,包括其name
,创建此结构的实例以传递给startScanning
并存储它们[String:Beacon]
字典中的实例。使用UUID的字符串作为密钥。然后,我们将给您回电,您可以使用信标标识符从字典中找到相应的Beacon
并获取其name
。
关于距离为何总是未知的原因,戴维是对的。您将在didRangeBeacons
回调中收到4个信标。由于您只有一个物理信标,除了当前活动的信标之外,所有其他信标都是未知的,但是您只看第一个。
您可能会发现,使用每个信标只有一行的表格视图比使用单个标签更容易。