Since recently, I get in the Xcode logs a lot of strange warnings from the CoreMotion framework, related to function getLocationForBundleID:
[Client] {"msg":"#NullIsland Either the latitude or longitude was exactly 0! That's highly unlikely", "latIsZero":0, "lonIsZero":0}
[Client] {"msg":"#NullIsland Received a latitude or longitude from getLocationForBundleID that was exactly zero", "latIsZero":0, "lonIsZero":0, "location":'28 5B E0 D7 EB 7F 00 00'}
I do not see any malfunction of my app. So maybe these logs can be ignored, but they are annoying anyway.
My questions are:
How can I correct a potential error?
How can I stop these warnings?
Apparently this error message is logged if property location of a CLLocationManager is read, before the CLLocationManager delivered the very first location.
My solution is the following:
I use anyway a subclass of CLLocationManager that allows me to set the location property for tests programmatically.
This is done as follows:
private var _location: CLLocation?
#objc dynamic override var location: CLLocation? {
get {
let usedLocation = _location ?? super.location // Here the error is logged if no location has been delivered yet
return usedLocation
}
set {
_location = newValue
}
}
This subclass has now an additional property
var anyLocationDelivered = false
that is set true in
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
locationManager.anyLocationDelivered = true
// …
}
and the getter is now
get {
guard anyLocationDelivered else { return nil }
let usedLocation = _location ?? super.location
return usedLocation
}
Now this error message is no longer logged.
I was getting this same error when trying to get a user's location in an app. There were two things preventing me from getting a valid lat/long. The main issue I was having was that I was using a simulator and had to set the location manually. If you're using the simulator, go to XCode, click Debug --> Simulate Location, and choose a location. I also had to make sure the correct location permission keys were added to Info.plist. You're also probably already aware, but you'll know if any keys are missing from Info.plist because a separate error message will print out to the console above or below these lat/long error messages, and it will tell you which key is missing. So basically:
Make sure you have all necessary location permissions accepted on the device/simulator being used to test the application.
Once you have location permissions, set a location if using a simulator.
Not sure if this will help at all, but I hope it does. If you've already confirmed that these are not issues, I'm not sure what may be causing the issue in your case, but stepping through the parts of your code responsible for fetching the user location would probably be beneficial to see which link in the process is failing.
The issue is likely that you ran your application on the simulator, which does NOT use your current location by default unless you manually change the simulation location in Debug, Simulate Location.
To fix the issue, either simulate your current location (as stated above) OR run your application on your physical signed device, close the application completely, and then relaunch your application.
OS_ACTIVITY_MODE = disable
To get rid of the warning do the following:
Steps
Navigate to Product -> Scheme -> Edit Scheme.
Open the Arguments tab
Environment Variables section add OS_ACTIVITY_MODE = disable
Related
I'm stumped, iOS 11.4 ( 15F79 ), iPhone 6. Cannot get the App to Ask for Motion Data. info.plist has been set via the editor and double checked via the info.plist open in textWrangler, Also deleted key and saved via textWrangler.
<key>NSMotionUsageDescription</key>
<string>This app needs your Phones motion manager to update when the phone is tilted. Please allow this App to use your phones tilt devices</string>
I have deleted then reinstalled the app about 10 times. I have restared the phone 5 times. I have checked through settings and my app does NOT show up in Privacy-Motion and Fitness or anywhere else in settings. I am using a free developer account, maybe that has something to do with it?
I created a new Xcode game template and changed nothing apart from importing CoreMotion and this code
**** Edited, sorry I forgot to say I had started the instance, just forgot to put it here, just in case someone thinks that's the problem ************
let motionManager = CMMotionManager()
override func didMove(to view: SKView) {
motionManager.startDeviceMotionUpdates()
if motionManager.isDeviceMotionActive == true {
motionManager.accelerometerUpdateInterval = 0.2
motionManager.startAccelerometerUpdates(to: OperationQueue.current!, withHandler: {
(accelerometerData: CMAccelerometerData!, error: NSError!) in
let acceleration = accelerometerData.acceleration
print(accelerometerData)
} as! CMAccelerometerHandler)
}else{
print(CMMotionActivityManager.authorizationStatus().rawValue)
}
which prints a 0 ( an Enum - case not determined ) to the console.
In my actual app it was a 3 ( same Enum - case Denied ).
As I've said, I have uninstalled, reinstalled, edited plist via Xcode and text wrangler ( a code editor ) , tried different versions of the code above, tried the code in different places ( in did move to view, in class )tried code off apple docs. etc.... I haven't been asked the NSUsage question and the App keeps crashing.
I have looked for ways to get the Alert fired up, As in CLLocationManager.requestWhenInUseAuthorization() but I cannot find a comparable CMMotion version ( I don't think there is one. ) I have created a new swift file , imported Foundation and CMMotion and just put that code there, But still no Alert asking for Motion Data.
I tried a single view app template instead of a game template thinking that might be the issue, Nope.
What do I do?
Any help Appreciated. Thanks
You are confusing two related but different classes.
CMMotionManager gives access to accelerometer, magnetometer and gyroscope data. It does not require any user permission as this information is not considered privacy related.
In your else clause you are checking the authorisation status of CMMotionActivityManager. This object reports the device motion type (walking, running, driving). This information is considered privacy related and when you create an instance of this class and request data from it, the permissions alert is displayed.
The reason your else is being triggered is because you are checking isDeviceMotionActive; this will be false until you call startDeviceMotionUpdates, which you never do. Even if you used isAccelerometerActive you would have a problem because you call startAccelerometerUpdates in the if clause which will never be reached.
You probably meant to check isAccelerometerAvailable. If this returns false then there isn't much you can do; the device doesn't have an accelerometer.
Update
It doesn't make sense to check isDeviceMotionActive immediately after calling startDeviceMotion:
You know it's active; you just started it
I imagine the start up takes some time, so you could expect to get false if you check immediately.
Apple recommends that you do not have more than one observer in place for each motion device type, so the purpose of check the is...Active to ensure you don't call start... again if you have already done so.
If you only want gyroscope data then you don't need to call startDeviceMotionUpdates at all.
Ive been trying for a few days now to set a pin high (Estimote location beacon) from an app I'm building.
Im doing something wrong as i am getting an error when the block fires off. Error is: [ESTTelemetryInfo portsData]: unrecognized selector sent to instance...
Ive looked everywhere for a snippet but can't find anything. I only want to be able to set the pin high (i don't need to send any data). If i can set the pin high i figure i could set it low when done using the same methods. This is the code:
let telem = ESTTelemetryInfo.init(shortIdentifier: "xxxxxxxxxxxxxxxx")!
let setPinHigh = ESTTelemetryNotificationGPIO.init(notificationBlock: { (telemInfo) in
if telInfo.shortIdentifier! != "xxxxxxxxxxxxxxxx" { return }
telemInfo.portsData.setPort(.port0, value: .high)
})
setPinHigh.fireNotificationBlock(with: telem)
Any help would be greatly appreciated.
ps Sorry if this is incorrectly formatted (long time reader first time poster).
Cheers
Gary
Fixed..we'll sort of. For anyone wanting to know the right way to to set a pin high, in output mode, is to connect to the beacon first through the device manager: ESTDeviceManager() -set the delegate in the class as ESTDeviceManagerDelegate - startDeviceDiscovery(with: deviceFilter) then in the delegate method:
func estDeviceConnectDidSucceed(_ device: ESTDeviceConnectable) { self.settings.gpio.portsData.setPort(.port0, value: .high)
}
BUT -> at the moment there is a bug that portsData has no member 'setPort'. I've filed a bug issue with Estimote on GitHub. Will come back to report once it's fixed.
I am using the GoogleMaps SDK (maps & places). For some reason the following callback is not being called. I have put loggers in there but nothing happens.
var placesClient : GMSPlacesClient?
...
func run(){
self.placesClient?.currentPlaceWithCallback({ (list: GMSPlaceLikelihoodList?, error: NSError?) -> Void in
if let error = error {
println("error: \(error.description)")
return
}
if let list = list {
self.renderList(list)
}
})
}
For some reason the block in currentPlaceWithCallback does not get called. Yesterday it happened because my API had a wrong bundle identifier, after changing which it started working. But today it stopped.
Any idea why this would happen ? Also, are we exposed to any API logs by Google ?
I was getting the same issue on my iPhone 6 device AND iPhone 6 simulator.
The fix was to add the NSLocationWhenInUseUsageDescription permission in Info.plist! But, it worked only on my iPhone 6 device, NOT the simulator.
As mentioned in the Google Place Guide:
(https://developers.google.com/places/ios-api/start)
Please note, as this sample requires access to the location of the device to get the current location, you will need to set the NSLocationWhenInUseUsageDescription key with appropriate explanatory text in your project's Info.plist file. For more details, see the guide to getting current place.
Now, the way I got it working on the iPhone simulator was by changing my location on the Simulator: Debug -> Location. That is, it was set to 'Apple' by default, I just changed it to Bicycle Ride.
It worked for me, may not for all.
So I am trying to get CLFloor in Core Location to give me data instead of returning nil in Swift, but I have not been able to. I have tried my own code and the following from NSHipster:
import CoreLocation
class LocationManagerDelegate: NSObject, CLLocationManagerDelegate {
func locationManager(manager: CLLocationManager!, didUpdateLocations locations: AnyObject[]!) {
let location: CLLocation? = locations[0] as? CLLocation
if let floor: CLFloor? = location?.floor {
println("Current Floor: \(floor?.level)")
}
}
}
let manager = CLLocationManager()
manager.delegate = LocationManagerDelegate()
manager.startUpdatingLocation()
Does anybody know how to make this work on a device or in the simulator, I'm sure the answer would benefit a lot of people. If anyone knows of any good resources on this or CLVisit, that would also be helpful.
As far as I understand what was said in WWDC session 708 - Taking Core Location Indoors, You need to manually register and set up the particular venue on the new Apple's Maps Connect page in order to get the floor information in iOS.
Therefore, it seems there is no way that the floor info is provided automatically (e.g. based altitude information from on GPS) for an arbitrary venue.
based on these 2 links from Apple's website
CLFloor Ref
CLLoaction Class Ref
Discussion
If floor information is not available for the current location, the value of this property is nil.
I'm not expert in swift but i think
returns nil possibly means that there is no floor information at that location.
I don't think iOS will magically tell you the floor level from what I understand https://developer.apple.com/videos/wwdc/2014/?id=708. You need to somehow get that number in another way. E.g. you may capture some iBeacon signal and from that download the floor level number, or swipe on your screen to find the correct floor map you are on?
I'm trying to use MapKit on iOS 8 and I keep getting the error:
Trying to start MapKit location updates without prompting for location authorization. Must call
-[CLLocationManager requestWhenInUseAuthorization] or -[CLLocationManager
requestAlwaysAuthorization] first.
Looking it up here, I found that I had to implement NSLocationWhenInUsageDescription in my plist and also make a call to locationManager.requestWhenInUseAuthorization() but nothing happens and I still get that error in the console. What am I doing wrong?
In my application delegate I made an optional var for the locationManager outside the class and then set
locManager = CLLocationManager()
locManager!.requestWhenInUseAuthorization()
This causes the alert view to pop up with your NSLocationWhenInUseUsageDescription or NSLocationAlwaysUsageDescription if you change it appropriately.
Then in the view controller file I made another var outside the class to hold a local CLLocationManager. I then set
if locManager {
locMan = locManager!
locMan!.delegate = self
}
Then you can use the delegate method
func locationManager(_manager: CLLocationManager!,didChangeAuthorizationStatus status: CLAuthorizationStatus)
which gets called when the authorisation status changes, which it does when the user responds to the pop up. Inside this you can use this bit of code to put the user location on the map
if status == CLAuthorizationStatus.AuthorizedWhenInUse {
map.showsUserLocation = true
}
will add the users location to the map only if you are authorised for when in use.
I have been bothered by that one as well, until I realized that the info.plist key has changed. If you had NSLocationUsageDescription in, you will need to change to either NSLocationAlwaysUsageDescription or NSLocationWhenInUseUsageDescription (set at least one to YES), it is now mandatory in iOS8.
And then, Robert's code works, as it should (thanks for sharing).
It is NSLocationWhenInUseUsageDescription, not NSLocationWhenInUsageDescription. Most places online have the wrong key