Wrong initial user location in MapView gps - swift

I want to get the user location, that's what I did:
I set locationManager in my ViewController:
var locationManager = CLLocationManager()
func setUpLocationManager() {
locationManager.delegate = self
locationManager.distanceFilter = 5
locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation
mapView?.showsUserLocation = true
locationManager.startUpdatingLocation()
}
Here is the function that is called once the location is updated:
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if !locations.isEmpty {
print("\(locations[0])")
}
}
}
It prints the initial location of the user position (see image), but I consider it wrong, because it an approximation.
I also tried with:
func mapView(_ mapView: MKMapView, didUpdate userLocation: MKUserLocation) {
let accuracy = userLocation.location?.horizontalAccuracy
if accuracy == locationManager.desiredAccuracy {
print("\(locations[0])")
}
}
But it never prints the location because locationManager.desiredAccuracy is equal to -2 and accuracy is always > 0.
This what I see on the mapView:
Initially the user pin shows a position near to the real position (but it is not right), subsequently the user pin moves to the real user position.
I want the function didUpdateLocations to be called when the user pin is on the right position.
My question is similar to this, but it was in objective-c.
Any hints? Thanks

ref. MKMapView's user location is wrong on startup or resume
Swift version:
func mapView(_ mapView: MKMapView, didUpdate userLocation: MKUserLocation) {
let accuracy = userLocation.location?.horizontalAccuracy
if accuracy ... {
}
}

Related

Geofence didExitRegion is never called

I'm trying to implement Geofencing into an app I'm working on. currently, I'm unable to pass the
desired output to the console because didExitRegion is never called.
What might be the cause of this and how may I go about solving it?
import SwiftUI
import MapKit
struct MapView: UIViewRepresentable {
var locationManager = CLLocationManager()
func setupManager() {
locationManager.desiredAccuracy = kCLLocationAccuracyBest
//locationManager.requestWhenInUseAuthorization()
locationManager.requestAlwaysAuthorization()
// Set Geofencing region
let geofencingRegion: CLCircularRegion = CLCircularRegion(center: CLLocationCoordinate2DMake(30.510074, 114.330510), radius: 100, identifier: "Wuhan")
geofencingRegion.notifyOnExit = true
geofencingRegion.notifyOnEntry = true
// Start monitoring
locationManager.startMonitoring(for: geofencingRegion)
}
func makeUIView(context: Context) -> MKMapView {
setupManager()
let mapView = MKMapView(frame: UIScreen.main.bounds)
mapView.showsUserLocation = true
mapView.userTrackingMode = .follow
return mapView
}
func updateUIView(_ uiView: MKMapView, context: Context) {
}
}
class MapAppDelegate: UIResponder, UIApplicationDelegate, CLLocationManagerDelegate {
var locationManager: CLLocationManager?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
self.locationManager = CLLocationManager()
self.locationManager!.delegate = self
return true
}
}
extension MapAppDelegate{
func locationManager(_ manager: CLLocationManager, didExitRegion region: CLRegion) {
print("Hello World")
}
func locationManager(_ manager: CLLocationManager, didEnterRegion region: CLRegion) {
print("Welcome Home")
}
}
The output I'm getting is multiple iterations of
2020-12-11 18:41:29.916937+0800 Geofencing[4225:235542] [VKDefault] Style Z is requested for an invisible rect
I want to create a state to check whether the user has entered the area or left the area to pull other view controllers on my MainView so I'm starting here.
The reason didExitRegion is never called is that you are not setting the CLLocationManager delegate.
In MapView you are creating an instance of CLLocationManager and then calling .startMonitoring on this instance. But you never set the delegate on this instance.
True, you are setting the delegate on the instance you created in your MapAppDelegate, but that is not the instance on which you are calling .startMonitoring.
You should refactor your code in such a way that you only create a single instance of CLLocationManager, and be sure to set the delegate on that instance.

Why my didUpdate userLocation method doesn't get called?

I have a MapKit in my view, and I want to access the userLocation data. However, the actual function
func firstMapView(_ firstMapView: MKMapView, didUpdateUserLocation userLocation: MKUserLocation){
print("it never gets called")
}
never ends up being called.
The whole code looks like this:
import UIKit
import MapKit
import CoreLocation
class ViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate{
#IBOutlet weak var firstMapView: MKMapView!
let locationManager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestWhenInUseAuthorization()
firstMapView.delegate = self
}
func firstMapView(_ firstMapView: MKMapView, didUpdateUserLocation userLocation: MKUserLocation){
print("it never gets called")
}
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
if status == .authorizedWhenInUse {
print("Authorized when in use detected")
locationManager.startUpdatingLocation()
firstMapView.showsUserLocation = true
}
}
}
When I run the code I get the debug message: print("Authorized when in use detected")
I saw this question, and tried to copy the things, but it didn't help.
Use this delegate function
func mapView(mapView: MKMapView!, didUpdateUserLocation userLocation: MKUserLocation!) {
print(userLocation)
}
delete this one
func firstMapView(_ firstMapView: MKMapView, didUpdateUserLocation userLocation: MKUserLocation){
print("it never gets called")
}

Swift 3 Rotate Map With User Direction

Currently my swift Application has a mapview with various annotations, is there a way when the user is walking from various annotations on the map to not be always locked in the north direction? I want the map to turn in the direction that they are walking instead of always pointing north.
Here is my current updatelocation function
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation])
{
let location = locations[0]
let myLocation:CLLocationCoordinate2D = CLLocationCoordinate2DMake(location.coordinate.latitude, location.coordinate.longitude)
let region:MKCoordinateRegion = MKCoordinateRegionMake(myLocation, noteTime.span)
map.setRegion(region, animated: true)
self.map.showsUserLocation = true
map.tintColor = UIColor(red:0.19, green:0.69, blue:0.73, alpha:1.0)
}
Should I declare it in here?
This example will update the rotation of the mapView to be pointing in the same direction as the user.
import UIKit
import MapKit
import CoreLocation
class ViewController: UIViewController, CLLocationManagerDelegate {
#IBOutlet weak var mapView: MKMapView!
let locationManager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
locationManager.delegate = self
locationManager.startUpdatingHeading()
}
func locationManager(_ manager: CLLocationManager, didUpdateHeading newHeading: CLHeading) {
mapView.camera.heading = newHeading.magneticHeading
mapView.setCamera(mapView.camera, animated: true)
}
}
Is that what you were after? I hope that helps :)

unable to get user location on map in swift xcode 7.1

I try to get the accurate location of the user on map but i only received the city name not exact location. Here is the code.
import UIKit
import MapKit
import CoreLocation
class ViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate
{
#IBOutlet weak var mapView: MKMapView!
let locationManager = CLLocationManager()
override func viewDidLoad()
{
super.viewDidLoad()
self.locationManager.delegate = self
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
self.locationManager.requestWhenInUseAuthorization()
self.locationManager.startUpdatingLocation()
self.mapView.showsUserLocation = true
}
override func didReceiveMemoryWarning()
{
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation])
{
let location = locations.last! as CLLocation
let center = CLLocationCoordinate2D(latitude: location.coordinate.latitude, longitude: location.coordinate.longitude)
let region = MKCoordinateRegion(center: center, span: MKCoordinateSpan(latitudeDelta: 1, longitudeDelta: 1))
self.mapView.setRegion(region, animated: true)
}
func locationManager(manager: CLLocationManager, didFailWithError error: NSError)
{
print("Error: " + error.localizedDescription)
}
}
NSLocationWhenInUseUsageDescription add in plist file.
Any help. Thankyou
If you are looking this in simulator. Then follow this process to zoom map. so that you can see streets in map
Press Option/Alt key --> you will see two rounds.
pinch it in/out for zoom in/out

Google API Maps don't show up on TabBar Application

I am learning about Google Maps and it works perfectly in a SingleView Application.
However I wanted to improve my app and have used a Tab Bar menu. I connected my ViewController with MapView to TabBarController and then map fails to load, there is just blank square instead of a map.
What did I do wrong?
EDIT:
class ViewController: UIViewController, CLLocationManagerDelegate {
#IBOutlet weak var mapView: GMSMapView!
let locationManager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
self.locationManager.requestWhenInUseAuthorization()
self.locationManager.delegate = self
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
self.locationManager.startUpdatingLocation()
self.locationManager.startMonitoringSignificantLocationChanges()
}
//MARK: Shows Google Map
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
self.locationManager.stopUpdatingLocation()
let locationArray = locations as NSArray
let locationObj = locationArray.lastObject as! CLLocation
let coord = locationObj.coordinate
mapView.camera = GMSCameraPosition(target: coord, zoom: 15, bearing: 0, viewingAngle: 0)
locationManager.stopUpdatingLocation()
}
func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
if status == .AuthorizedWhenInUse {
locationManager.startUpdatingLocation()
mapView.myLocationEnabled = true
mapView.settings.myLocationButton = true
}
}
I think I found the problem, at least now everything works.
So I moved
mapView.myLocationEnabled = true
mapView.settings.myLocationButton = true
to func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) before locationManager.stopUpdatingLocation() and now it works.
However I do have a feeling that my code is bad, it uses stopUpdatingLocation() twice. In my case does it mean, that app will get user location only once when the app laods?