如何监视多个iBeacon并根据每个信标更改UILabel?

时间:2019-07-10 18:24:39

标签: ios swift ibeacon beacon

我在同时监视多个信标时遇到问题。我的代码只能使用一个,但是我似乎无法弄清楚如何监视多个信标并更新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中设置的信标的标识符。

2 个答案:

答案 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个信标。由于您只有一个物理信标,除了当前活动的信标之外,所有其他信标都是未知的,但是您只看第一个。

您可能会发现,使用每个信标只有一行的表格视图比使用单个标签更容易。