问题
I have an app that does geofencing. When I run it in the Simulator (Xcode 8.3.3 and Xcode 9), everything seems to work with the exception that my CLLocationManager didEnterRegion is never called.
It is called just fine when I run the app on my iPhone, either out in the real world (entering a region) or in Xcode via location simulation.
Any idea why this would be?
One difference I've discovered is that the simulator only supports monitoring location when in use, so I had to set things up so I had had both permission strings in my plist file, but other than that I'm stumped.
Since I'm not providing code (it's way too complex and distributed in my app), let me note what is working in the simulator:
In my app's scheme, I have 'Allow Location Simulation' checked and I have a have a few .gpx files added for locations I'm monitoring. I have a default location set.
My location manager delegate is being called when I start up. I get .authorizedWhenInUse in the Simulator and .authorizedAlways on the phone.
locationManager(:didUpdateLocations:) is being called when the location changes.
When didUpdateLocations is called, I do the following:
for r in manager.monitoredRegions { if let cr = r as? CLCircularRegion { if cr.contains(location.coordinate) { log.debug("Am in the region!") } else { let crLoc = CLLocation(latitude: cr.center.latitude, longitude: cr.center.longitude) log.debug("distance is: \(location.distance(from: crLoc))") } }
and it works. So my regions are being monitored and my location is where I think it should be.
Finally, my locationManager delegate's monitoringDidFailFor and didFailWithError are NOT being called. Not that they've never been - they have during development, but not now.
So I'm stumped. Again, it works fine on the phone and not in the simulator.
What am I doing wrong?
回答1:
Ok, I found the problem. First, there is a change needed for Xcode 9/iOS 11. I had filed a bug with Apple and received the following:
In iOS11 all applications must support WhenInUse authorization if they support Always authorization. With this change the Location Services usage description keys have changed. For an application to get an Always prompt to show they must have both NSLocationAlwaysAndWhenInUseUsageDescription and NSLocationWhenInUseUsageDescription in their App’s Info.plist.
So if you are calling: locationManager.requestAlwaysAuthorization()
, for iOS 11, you need to have both NSLocationAlwaysAndWhenInUseUsageDescription
and NSLocationWhenInUseUsageDescription
. If you want your app to keep working on pre-iOS 11 you need to also keep the NSLocationAlwaysUsageDescription
, so you'll have 3 keys.
I confirmed this with Ray Wenderlich tutorial that Kuhncj's referenced. As is, it doesn't work with Xcode 9, but does with Xcode 8.
My problem was an error in my part. While I had the 3 correct keys, but in reviewing where I asked for permissions, I had the following:
var permission : Permission = SimulatorPlatform.isSimulator ? .locationWhenInUse : .locationAlways
So I was basically running different code for the simulator vs the device. After changing that, my app did get called arriving at a monitored region.
回答2:
For iOS 11 use the following in your info.plist:
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>Need Location</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>Need Location</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Access For Location</string>
来源:https://stackoverflow.com/questions/44722395/locationmanager-didenterregion-not-called-in-xcode-9-simulator