SWIFT: CoreLocation - ранжирование маяков с использованием CLBeaconIdentityConstraint не охватывает несколько маяков - PullRequest
1 голос
/ 17 марта 2020

Итак, мы столкнулись с проблемой, развивающейся в Swift для iOS 13. Когда мы используем более новый метод для ранжирования маяков «startRangingBeacons (удовлетворяющий: CLBeaconIdentityConstraint)», он будет ранжировать только последний добавленный маяк, поэтому, если есть Есть более одного маяка, у нас есть проблемы. Когда мы используем более старый метод startRangingBeacons (in: region), он устарел, но все еще функционирует в iOS 13, приложение работает должным образом.

Подробности (используя более новый метод с «ограничениями»):

  1. Приложение запускает мониторинг двух областей маяка
  2. Запускает дальние маяки, если пользователь вводит BeaconRegion
  3. Включите Beacon1, приложение начинает диапазон Beacon1
  4. Включите Beacon2, приложение начинает диапазон Beacon2, но не определяет диапазон Beacon1. (ПРИМЕЧАНИЕ. Обе области маяков перекрываются, и более старый метод может справиться с этим)

Когда ранжированные маяки с startRangingBeacons (in: region), приложение смогло выбрать оба маяка.

Когда последний маяк дальнего радиуса действия выключен, событие didRangeBeacons запускается с пустым списком CLBeacon, в котором все еще должен быть другой маяк, но это не так.

Вот код, который не работает:

    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()
                 }
             }
         }
    }
}

Вот код, который работает:

    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)
                }
            }
        }
    }
}

Создание маяков для мониторинга:

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

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
    }
}

Вот код для начала ранжирования. Комментируемый звонок внизу работает по желанию. Вызов без комментариев выше, это вонючий. W создает ограничение в строке в вызове, просто UUID. Он работает для одного маяка, но как только мы добавляем второй (с другим UUID, как отмечено выше), он охватывает только самые последние данные.

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

Как получить диапазон всех маяков с помощью более нового метода "тонадежные ограничения "?

...