I have an app that tracks the journeys of the user.
I noticed that in background, from iOS 13.3, the system slows down the sending of locations when the speed slows down. In case of high speed, the location are sent every second. Is this possible? Could it be a bug? This is my location manager:
locationManager.distanceFilter = kCLDistanceFilterNone
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.pausesLocationUpdatesAutomatically = false
locationManager.activityType = .other
locationManager.allowsBackgroundLocationUpdates = true
Related
Sometimes location manager gives GPS-point, which is located about hundreds meters, or several kilometers away from real device location. After it location manager continues provide us with wrong coordinates, which slowly became closer to real device location.
Such points have quite good accuracy about ~30 - ~65 meters, and some of them have speed > 0 m/s.
real path was:
Authorization status is "Always allow"
location manager is adjustment:
CLLocationManager *manager = [CLLocationManager new];
manager.allowsBackgroundLocationUpdates = YES;
manager.pausesLocationUpdatesAutomatically = NO;
manager.showsBackgroundLocationIndicator = YES;
manager.distanceFilter = 50; // meters
manager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
manager.delegate = self;
This problem is actual only for iOS 13. I made about 50 experiments, registering movement trajectories of ~5 km - ~150 km length. Same code works perfectly with iOS 12.
I am using iOS Google Maps in my app. I've been looking for memory leaks as of lately as I noticed the Memory started spiking whenever I would zoom out. Both on simulator and my actual iPhone X device experience such memory spikes when zooming out. I am also zooming out because I am using the marker clustering feature.
I've done some research on different ways to detect memory leaks such as enabling sound actions on breakpoints and looking at Backtrace tree for strong references. It seems that there is a strong reference when I configure my GMSMapView (Code below).
func configureMapView() {
guard let location = locationManager.location else { return }
let camera = GMSCameraPosition.camera(withLatitude: location.coordinate.latitude, longitude: location.coordinate.longitude, zoom: 16.5)
mapView = GMSMapView.map(withFrame: CGRect.zero, camera: camera)
mapView.isMyLocationEnabled = true
mapView.settings.compassButton = true
mapView.settings.rotateGestures = false
mapView.settings.tiltGestures = false
view = mapView
}
Xcode is pointing to this line that has a strong reference.
mapView = GMSMapView.map(withFrame: CGRect.zero, camera: camera)
Is this strong reference the reason why memory usage spikes up when zooming out? Also, not entirely sure how to fix this strong reference with Google Maps, any help would be appreciated!
I have 2 apps that use MKMapViews and they both previously worked fine, but now they won't show the user's location. Can anyone think of a reason this code wouldn't make a map show the user's blue dot?
mapView.showsUserLocation = YES;
mapView.mapType = MKMapTypeHybrid;
mapView.delegate = self;
I really appreciate any help, I'm stumped right now...
I am trying to make an app thats shows your speed (velocity) on a gauge (like in a car).
the problem I have is that CLlocationManager delegate method didUpdateLocations gives me a read of the location and the speed only once a second and so if I accelerate the car too fast i get delay with the needle position on the gauge.
for example: I get the speed 13 m/s and after one second i get 26 m/s and so the needle in the UI goes to 13 m/s and waits there for a second and only then goes to 26 m/s. so i get a non continuous movement of needle in the UI.
from reading other question i understood that i can't control the sample rate that I get from CLlocation and that i can't tell him to give me a read every 0.25 sec (with different values).
1. is is true?
2. how can I solve it so it will look good to the user?
//in viewdidload:
self.locationManager.delegate = self
self.locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation
self.locationManager.distanceFilter = kCLDistanceFilterNone
if versionNum == 8 {
self.locationManager.requestAlwaysAuthorization()
}
self.locationManager.startUpdatingLocation()
func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {
println(locations)
var loc = locations.last as! CLLocation
var speed = loc.speed
var time = loc.timestamp
var hour = getCurrentHour(time)
println("hour inside manager: \(hour)")
if hour == 18 && self.isItDay {
self.currentTimeHour = hour
self.setDayBool()
self.setRightImg()
}
else if hour == 6 && !self.isItDay {
self.currentTimeHour = hour
self.setDayBool()
self.setRightImg()
}
if self.unit == "MPH" {
speed = speed * 3.280839895013123
}
if speed >= 0 {
self.speedLabel.text = "\(Int(speed))"
self.animateNeedle(CGFloat(speed))
}
println("speed: \(speed)")
}
func animateNeedle(speed : CGFloat) {
var rotation : CGFloat = 0
if self.unit == "KMH" {
rotation = (speed * 4) - 5
}
else if self.unit == "MPH" {
rotation = speed + ((speed / 3) - 5)
}
if let trans = self.needleImg.layer.presentationLayer() {
self.currentValue = self.needleImg.layer.presentationLayer().valueForKeyPath("transform.rotation") as! Float
}
println(currentValue)
let rotateAnimation = CABasicAnimation(keyPath: "transform.rotation")
rotateAnimation.fillMode = kCAFillModeBoth
rotateAnimation.removedOnCompletion = false
rotateAnimation.fromValue = currentValue
rotateAnimation.toValue = self.degToRad(rotation)
rotateAnimation.duration = 0.3
self.needleImg.layer.addAnimation(rotateAnimation, forKey: "transform.rotation")
}
As Lefteris says, you should set your distance filter to 0. You should also select kCLLocationAccuracyBest as the desiredAccuracy property of your location manager.
iOS GPS is rather crude in any case, so I doubt if either of those things will help a whole lot.
I would suggest animating your speedometer needle from it's old position to the new. A duration of .2 - .3 seconds should be enough to create the impression of movement without taking so long that it interferes with keeping the needle position current.
You can use UIView animation methods like animateWithDuration:animations, or Core Animation. Core Animation is a lot harder to use but offers more options.
You need to set the distance filter that notify changes:
/* Notify changes when device has moved x meters.
* Default value is kCLDistanceFilterNone: all movements are reported.
*/
self.locationManager.distanceFilter = 10.0f;
From Apple Documentation:
For more option look at this full example:
self.locationManager = [CLLocationManager new];
self.locationManager.purpose = #"Tracking your movements on the map.";
self.locationManager.delegate = self;
/* Pinpoint our location with the following accuracy:
*
* kCLLocationAccuracyBestForNavigation highest + sensor data
* kCLLocationAccuracyBest highest
* kCLLocationAccuracyNearestTenMeters 10 meters
* kCLLocationAccuracyHundredMeters 100 meters
* kCLLocationAccuracyKilometer 1000 meters
* kCLLocationAccuracyThreeKilometers 3000 meters
*/
self.locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters;
/* Notify changes when device has moved x meters.
* Default value is kCLDistanceFilterNone: all movements are reported.
*/
self.locationManager.distanceFilter = 10.0f;
/* Notify heading changes when heading is > 5.
* Default value is kCLHeadingFilterNone: all movements are reported.
*/
self.locationManager.headingFilter = 5;
// update location
if ([CLLocationManager locationServicesEnabled]){
[self.locationManager startUpdatingLocation];
}
You need to set the distance filter to 0:
self.locationManager.distanceFilter = kCLDistanceFilterNone;
Also as Massimo mentioned above, you should also change the desired accuracy:
self.locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
I am calculating the distance between two locations like below
CLLocation *locA = [[CLLocation alloc] initWithLatitude:lat longitude:lon];
CLLocationCoordinate2D coordinate = [self getLocation];
CLLocation *locB = [[CLLocation alloc] initWithLatitude:coordinate.latitude longitude:coordinate.longitude];
CLLocationDistance distance = [locA distanceFromLocation:locB];
CLLocationDistance kilometers = distance / 1000.0;
But it giving the different result when i connect to wifi and 3G network.how to get the same result for both.
You invariably will not get the same location for both. In fact, if you come back to the exact same location tomorrow and turn on location services, you might not get the same latitude and longitude even if you stayed with the same technology.
The latitude and longitude you receive from a CLLocationManager is not an exact science. In fact, if you look at the original CLLocation objects you received, you'll notice that there is a horizontalAccuracy property that reflects how accurate/inaccurate the coordinate could be. When you first start location services, you'll even see multiple locations come in, generally with increasing accuracy.
But it will never be perfect and you shouldn't expect it to be. This is one of the reasons why it's important to test location-aware code on a real device, because the simulator will lull one into a false sense of absolute accuracy which doesn't exist in the real world. You should write code that anticipates this. And, if nothing else, you should start considering horizontalAccuracy of the objects you receive from the location manager.
there's nothing wrong in the code lines you posted,
the only line that could give you differences in the 2 cases (wifi and 3g) is your method [self getLocation]
where i guess you get the device location.
In this case your device may use both gps and wifi access to calculate its location, so little differences may occurs (you may have noticed that some map applications advice you to turn your wifi on to get more accuracy)
Anyway,
in your getLocation method try to add a more precise accuracy when you use
CLLocationManager
i tried this:
- (CLLocationCoordinate2D )getLocation {
self.locationManager = [[CLLocationManager alloc] init];
locationManager.distanceFilter = kCLDistanceFilterNone; // whenever we move
locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters; // 100 m
[locationManager startUpdatingLocation];
CLLocationCoordinate2D startCoord = CLLocationCoordinate2DMake(locationManager.location.coordinate.latitude, locationManager.location.coordinate.longitude);
return startCoord;
}
and the accuracy is enough to get no differences between 3G/wifi
but you could set it to
kCLLocationAccuracyBestForNavigation;
kCLLocationAccuracyBest;
kCLLocationAccuracyNearestTenMeters;
ps
i hope you are using a device with GPS, of course...