Why my didUpdate userLocation method doesn't get called? - swift

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")
}

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.

Make custom location annotations in using Mapbox

I am using Mapbox to create my app. When I click a button I would like it to mark my current location and add a marker to it as it currently does. I then would like the abiilty to tap on this marker and have it display the current location information such as the adress of the marked point.
Right now all I have is...
https://imgur.com/a/RSx0G
I would like to note that I am using Xcode 9.1 and Swift 4. Thank you for all your feedback in advance.
Currently the swift file looks like...
import Foundation
import UIKit
import CoreLocation
import Mapbox
import MapKit
import MapboxGeocoder
class SecondViewController: UIViewController, CLLocationManagerDelegate, MGLMapViewDelegate, UITextFieldDelegate {
let geocoder = Geocoder.shared
let dismissesAutomatically: Bool = false
let isAnchoredToAnnotation: Bool = true
weak var delegate: MGLCalloutViewDelegate?
let tipHeight: CGFloat = 10.0
let tipWidth: CGFloat = 20.0
#IBOutlet var mapView: MGLMapView!
let manager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
manager.delegate = self
manager.desiredAccuracy = kCLLocationAccuracyBest
manager.requestWhenInUseAuthorization()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
#IBAction func markStuff(_ sender: Any) {
}
#IBAction func refLocation(_ sender: Any) {
manager.startUpdatingLocation()
}
func mapView(_ mapView: MGLMapView, annotationCanShowCallout annotation: MGLAnnotation) -> Bool {
return true
}
func mapView(_ mapView: MGLMapView, viewFor annotation: MGLAnnotation) -> MGLAnnotationView? {
return nil
}
func mapView(_ mapView: MGLMapView, tapOnCalloutFor annotation: MGLAnnotation)
{
print("tap on callout")
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location = locations[0]
let center = CLLocationCoordinate2D(latitude: location.coordinate.latitude, longitude: location.coordinate.longitude)
mapView.setCenter(center, zoomLevel: 10, animated: true)
let annotation = MGLPointAnnotation()
annotation.coordinate = location.coordinate
mapView.selectAnnotation(annotation, animated: true)
annotation.title = "Testing"
annotation.subtitle = "\(annotation.coordinate.latitude), \(annotation.coordinate.longitude)"
self.mapView.addAnnotation(annotation)
manager.stopUpdatingLocation()
You can create a subclass of MGLUserLocationAnnotationView, then use that as your view for the MGLUserLocation annotation.
For example, if your custom subclass was called YourLocationAnnotationView(), you could do something like:
func mapView(_ mapView: MGLMapView, viewFor annotation: MGLAnnotation) -> MGLAnnotationView? {This custom view is created below.
if annotation is MGLUserLocation && mapView.userLocation != nil {
return YourLocationAnnotationView()
}
return nil
}
}
For a complete implementation, see this example from the official documentation.

CLLocationManager works only once

I'm new to swift - currently, my current location is only output once in the console when I first call setupLocationManager() on init through override func awakeFromNib(). When I want it to output my new location by calling locationManager.startUpdatingLocation() when I click a button with the method updateLocation(), it prints an error. Any way to fix this? All help is appreciated.
import Cocoa
import CoreLocation
class StatusMenuController: NSObject, CLLocationManagerDelegate {
#IBOutlet weak var statusMenu: NSMenu!
let statusItem = NSStatusBar.system().statusItem(withLength: NSVariableStatusItemLength)
var locationManager:CLLocationManager!
var currentLocation:CLLocation?
#IBAction func quitClicked(_ sender: NSMenuItem) {
NSApplication.shared().terminate(self)
}
#IBAction func updateClicked(_ sender: NSMenuItem) {
updateLocation()
}
func updateLocation() {
locationManager.startUpdatingLocation()
}
override func awakeFromNib() {
statusItem.menu = statusMenu
let icon = NSImage(named: "statusIcon")
icon?.isTemplate = true
statusItem.image = icon
statusItem.menu = statusMenu
setupLocationManager()
}
func setupLocationManager(){
locationManager = CLLocationManager()
locationManager?.delegate = self
//self.locationManager?.requestAlwaysAuthorization()
locationManager?.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
locationManager?.startUpdatingLocation()
}
// Below method will provide you current location.
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if currentLocation == nil {
currentLocation = locations.last
locationManager?.stopMonitoringSignificantLocationChanges()
let locationValue:CLLocationCoordinate2D = manager.location!.coordinate
print(locationValue)
locationManager?.stopUpdatingLocation()
}
}
// Below Method will print error if not able to update location.
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print("Error")
}
}
There is an if condition in the code which suspends updating the location after the location is set once (if currentLocation == nil). You have to reset currentLocation to nil before restarting the manager.
#IBAction func updateClicked(_ sender: NSMenuItem) {
currentLocation = nil
updateLocation()
}

Swift: Trying to get coordinates, but don't know how to call locationManager() function

I am trying to get the users latitude and longitude.
import Foundation
import CoreLocation
class locationModule: NSObject, CLLocationManagerDelegate {
var locationManager = CLLocationManager()
func getLocation() {
locationManager.delegate = self
locationManager.requestAlwaysAuthorization()
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.startUpdatingLocation()
}
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
var location: CLLocationCoordinate2D = (manager.location?.coordinate)!
print(location.latitude)
print(location.longitude)
}
}
This is code is in a seperate Swift file, So I need getLocation() to be able to call func locationManager, how would I call the locationManager function from the getLocation() function.
Your code is fine, but it's not being called, probably because you didn't add the key to your Info.plist.
For your code, add NSLocationAlwaysUsageDescription to your Info.plist, with a value such as All your base are belong to us, so I use your location whenever I want. as the String value. Then just start your locationManager somewhere like func applicationDidBecomeActive(application: UIApplication) like this:
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var locMod:locationModule?
func applicationDidBecomeActive(application: UIApplication) {
if ( locMod == nil )
{
locMod = locationModule()
}
locMod?.getLocation()
}
The first time, you will see the prompt, then you will see the location being logged.
FYI, here's how I organized the locationModule:
class locationModule: NSObject, CLLocationManagerDelegate {
var locationManager = CLLocationManager()
internal func getLocation() {
locationManager.delegate = self
locationManager.requestAlwaysAuthorization()
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.startUpdatingLocation()
}
// MARK : CLLocationManagerDelegate protocol
#objc
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
for location in locations {
print("\(location.coordinate.latitude), \(location.coordinate.longitude)")
}
}
}

Swift, CLLocationManagerDelegate in NSObject not working

i have problem with getting my location with CLLocationDelegate.
i created new subclass of UIView and work well, but when i created subclass of NSObject, CLLocationDelegate not called. I can find where is problem.
here is my code:
import UIKit
import CoreLocation
class LocationData: NSObject, CLLocationManagerDelegate {
var locationManager : CLLocationManager = CLLocationManager()
override init() {
super.init()
if self.locationManager.respondsToSelector(Selector("requestAlwaysAuthorization")) {
self.locationManager.requestWhenInUseAuthorization()
}
self.locationManager.delegate = self
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
self.locationManager.distanceFilter = 50
self.locationManager.startUpdatingLocation()
println("init LocationData")
}
func locationManager(manager: CLLocationManager!, didFailWithError error: NSError!) {
println(error.description)
}
func locationManager(manager: CLLocationManager!, didUpdateToLocation newLocation: CLLocation!, fromLocation oldLocation: CLLocation!) {
println("updated")
}
}
Thanks!
Your code is fine! But when instantiating the class, you need to do like this:
import UIKit
class ViewController: UIViewController {
let LocationData: LocationData = LocationData() //<- here is the secret to works!!!
override func viewDidLoad() {
super.viewDidLoad()
}
I also suggest that you change your init to something like this:
override init() {
super.init()
let authorizationStatus: CLAuthorizationStatus = CLLocationManager.authorizationStatus()
if authorizationStatus == .notDetermined {
locationManager.requestWhenInUseAuthorization()
}
self.locationManager.delegate = self
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
self.locationManager.distanceFilter = 50
self.locationManager.startUpdatingLocation()
print("init LocationData")
}
And don't forget to add NSLocationWhenInUseUsageDescription in the info.plist project.