因此,我们在 Swift for iOS 13 中开发时遇到了一个问题。当我们使用较新的方法来测距信标“startRangingBeacons(satisfying: CLBeaconIdentityConstraint )”时,它只会测距最近添加的信标,因此如果有多个信标, 我们出现了问题。当我们使用旧方法“startRangingBeacons(in:region)”(现已弃用但在 iOS 13 中仍然有效)时,应用程序按预期工作。
详细信息(使用带有“约束”的新方法):
- 应用程序开始监控2个Beacon区域
- 如果用户进入 BeaconRegion,则启动测距信标
- 打开Beacon 1,应用程序开始测距Beacon 1
- 打开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")]
信标数据定义
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)
}
我们如何让它使用较新的“满足约束”方法来确定所有信标的范围?