Swift2.3 code for Beacon detection

2019-01-23 09:52发布

问题:

We are in advanced stages of developing a Swift2.2 app and hence have decided to migrate to 2.3 in the interim and do the full Swift 3 migration later. However we are unable to get beacon detection working post conversion to Swift 2.3. The method "didRangeBeacons" keeps returning an empty array. The same code was working in Swift 2.2 so we know we have all the permissions etc in place.

Also if we open the "Locate" app on the same ipad then our app also starts returning data in "didRangeBeacons". Have tried various versions of the apps out there and all Swift2.3 apps are behaving the same way. Can't make out what the Locate app is doing... Anyone on the same boat??


Here is the code we are using. Am not sure this is supposed to be written here or in comments but couldn't put code within comments somehow...

import UIKit
import CoreLocation

class ViewController: UIViewController, CLLocationManagerDelegate {

let locationManager = CLLocationManager()
let region = CLBeaconRegion(proximityUUID: NSUUID(UUIDString: "9735BF2A-0BD1-4877-9A4E-103127349E1D")!, identifier: "testing")
// Note: make sure you replace the keys here with your own beacons' Minor Values


override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    self.locationManager.delegate = self
    self.locationManager.requestAlwaysAuthorization()
    self.locationManager.startMonitoringForRegion(self.region)
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

func locationManager(manager: CLLocationManager, didStartMonitoringForRegion region: CLRegion) {
    print("didStartMonitoringForRegion")
    self.locationManager.requestStateForRegion(region)
}

func locationManager(manager: CLLocationManager, monitoringDidFailForRegion region: CLRegion?, withError error: NSError) {
    print("monitoringDidFailForRegion")
}

func locationManager(manager: CLLocationManager, didDetermineState state: CLRegionState, forRegion region: CLRegion) {
    print("didDetermineState")
    if state == .Inside {
        //Start Ranging
        self.locationManager.startRangingBeaconsInRegion(self.region)
        self.locationManager.startUpdatingLocation()
    }
    else {
        //Stop Ranging here
        self.locationManager.stopUpdatingLocation()
        self.locationManager.stopRangingBeaconsInRegion(self.region)
    }
}

func locationManager(manager: CLLocationManager, didRangeBeacons beacons: [CLBeacon], inRegion region: CLBeaconRegion) {
    print(beacons.count)
}

}

[Update post some more attempts to get this working] App works in foreground mode if we remove self.locationManager.startMonitoringForRegion(self.region) and call self.locationManager.startRangingBeaconsInRegion(self.region) directly after self.locationManager.requestAlwaysAuthorization()

This is sub-optimal because we don't get entry and exit events or state but atleast we are getting beacon counts.

回答1:

There are a number of anecdotal reports of beacon detection problems on iOS 10. Symptoms include:

  • Improper region exit events, especially when the app is in the background, followed by entry events if the shoulder button is pressed.
  • Periodic dropouts in detections of ranged beacons, with callbacks providing an empty beacon list when beacons are in the vicinity.
  • Ranged beacon callbacks return proper results when a different beacon ranging or detection app is running that targets iOS 9.x.

This is presumably a bug that will be fixed in an iOS update. Until then, some users have reported that setting the app deployment target in XCode to 9.x will resolve the issue.



回答2:

Try constructing your location manager after the view loads. In other words, change:

let locationManager = CLLocationManager()

to

let locationManager : CLLocationManager!

And then add this to the viewDidLoad:

locationManager = CLLocationManager()

I have seen strange behavior with LocationManager constructed on initialization of a UIViewController.



回答3:

While I was testing beacon ranging, I downloaded multiple applications that I forgot to uninstall. After I uninstalled all beacon-related applications and re-installed just the needed applications, I was able to get ranging beacons to work.