SWIFT: CoreLocation - Ranging Beacons using CLBeaconIdentityConstraint does not range multiple beacons

僤鯓⒐⒋嵵緔 提交于 2020-04-16 02:59:29

问题


So, we have encountered a problem, developing in Swift for iOS 13. When we use the newer method for ranging beacons "startRangingBeacons(satisfying: CLBeaconIdentityConstraint )" it will only range the most recently added beacon, so if there are more than one beacon, we have a problem. When we use the older method, "startRangingBeacons(in: region)," now deprecated but still functional in iOS 13, the app works as expected.

Details (using the newer method with "constraints"):

  1. App StartsMonitoring 2 Beacon regions
  2. Starts Ranging Beacons if the user enters a BeaconRegion
  3. Turn on Beacon1, the app starts ranging Beacon1
  4. Turn on Beacon2, the app starts ranging Beacon2, but does not range beacon1. (NOTE - Both beacons regions overlap, and the older method can handle this)

When ranged beacons with startRangingBeacons(in: region), the app was able to range both beacons.

When the latest ranged beacon is turned off, didRangeBeacons event is triggered with empty CLBeacon list, which should still have the other beacon in, but it does not.

Here is the code that does not work:

    func locationManager(_ manager: CLLocationManager, didRange beacons: [CLBeacon], satisfying beaconConstraint: CLBeaconIdentityConstraint) {

     for beacon in beacons {
         if [.near, .immediate].contains(beacon.proximity){
             if let index = beaconsInProximity.firstIndex(of: beacon) {
                 beaconsInProximity.remove(at: index)
             }
             beaconsInProximity.append(beacon)
             if beaconsInProximity.count > 1 { beaconsInProximity = beaconsInProximity.sorted(by: {$0.accuracy < $1.accuracy})}
             if nearestBeacon == nil || !nearestBeacon!.isEqual(beaconsInProximity[0]) {
                 if(nearestBeacon != nil) {
                     notifyUser(isExiting: true, isBeacon = true)
                 }
                 nearestBeacon = beaconsInProximity[0]
                 displayOrSendNotification()
             }

         } else if let index = beaconsInProximity.firstIndex(of: beacon){
             if(beaconsInProximity.count > 1) {
                 beaconsInProximity.remove(at: index)
                 if nearestBeacon != nil && nearestBeacon!.isEqual(beacon) {
                     notifyUser(isExiting: true, isBeacon = true)
                     nearestBeacon = beaconsInProximity.count > 0 ? beaconsInProximity[0] : nil
                     displayOrSendNotification()
                 }
             }
         }
    }
}

Here is the code that works:

    func locationManager(_ manager: CLLocationManager,
                     didRangeBeacons beacons: [CLBeacon],
                     in region: CLBeaconRegion) {
    print("Did range beacons")

    for beacon in beacons {
        if [.near, .immediate].contains(beacon.proximity){
            if let index = beaconsInProximity.firstIndex(of: beacon) {
                beaconsInProximity.remove(at: index)
            }
            beaconsInProximity.append(beacon)
            if beaconsInProximity.count > 1 { beaconsInProximity = beaconsInProximity.sorted(by: {$0.accuracy < $1.accuracy})}
            if nearestBeacon == nil || !nearestBeacon!.isEqual(beaconsInProximity[0]) {
                if(nearestBeacon != nil) {
                    displayOrSendNotification(isExiting: true, isBeacon: true)
                }
                nearestBeacon = beaconsInProximity[0]
                displayOrSendNotification(isExiting: false, isBeacon: true)
            }

        } else if let index = beaconsInProximity.firstIndex(of: beacon){
            if(beaconsInProximity.count > 1) {
                beaconsInProximity.remove(at: index)
                if nearestBeacon != nil && nearestBeacon!.isEqual(beacon) {
                    nearestBeacon = beaconsInProximity.count > 0 ? beaconsInProximity[0] : nil
                    displayOrSendNotification(isExiting: false, isBeacon: true)
                }
            }
        }
    }
}

Creating beacons to monitor:

var regionsToMonitor = [
        BeaconData(uuid: UUID(uuidString: "82eee62a-b285-44dc-88e9-531188ee72e7")!, major: 0, minor: 1, name: "Dime Team", description: "Awesome Innovations", image: "beacon-icon"),
        BeaconData(uuid: UUID(uuidString: "c2db97d9-6e80-44a2-82f5-3987065ba4ea")!, major: 7, minor: 11, name: "Data Team", description: "Busy Team", image: "beacon-icon")]

BeaconData Definition

struct BeaconData: RegionData{

    let uuid: UUID
    let major: NSNumber
    let minor: NSNumber
    let beaconRegion: CLBeaconRegion
    let name: String
    let detail: String
    let image: String

    init(uuid:  UUID, major: NSNumber, minor: NSNumber, name: String, description: String, image: String) {
        self.uuid = uuid
        self.major = major
        self.minor = minor
        self.beaconRegion = CLBeaconRegion(beaconIdentityConstraint: CLBeaconIdentityConstraint(uuid: uuid), identifier: name)
        self.name = name
        self.detail = description
        self.image = image
    }
    init(uuid:  UUID, major: NSNumber, minor: NSNumber, beaconRegion: CLBeaconRegion, name: String, description: String, image: String) {
        self.uuid = uuid
        self.major = major
        self.minor = minor
        self.beaconRegion = beaconRegion
        self.name = name
        self.detail = description
        self.image = image
    }

    func contains(region: CLRegion) -> Bool {
        return self.beaconRegion == region
    }
}

Here is the code to start ranging. Commented call on the bottom works as desired. Uncommented call above that is the wonky one. W create the constraint inline in the call, just the UUID. It works for one beacon, but as soon as we add a second (with different UUID as noted above) it only ranges the most recent.

        for region in beaconRegionsToRange {
            print("Start Ranging \(region.uuid)")
            locationManager.startRangingBeacons(satisfying: CLBeaconIdentityConstraint(uuid: region.uuid))
            //locationManager.startRangingBeacons(in: region)
        }

How do we get it to range all beacons with the newer "satisfyingConstraints" method?

来源:https://stackoverflow.com/questions/60729509/swift-corelocation-ranging-beacons-using-clbeaconidentityconstraint-does-not

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!