Delegate must respond to locationManager:didFailWithError: even though implemented didFailWithError method - ios

For some reason Xcode thinks I'm not implementing didFailWithError method of the CLLocationManagerDelegate protocol
I fail to see what I'm doing wrong, as I literally copied from another SO post that said this didFailWithErrormethod was updated for Swift 3. So I don't understand why Xcode thinks I'm not implementing didFailWithError
Any insight would be greatly appreciated!
Code
class OptionsViewController: UIViewController,
CLLocationManagerDelegate {
var locationManager: CLLocationManager = CLLocationManager()
override func viewDidLoad() {
//Ask user for location
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
//Use users current location if no starting point set
if CLLocationManager.locationServicesEnabled() {
if CLLocationManager.authorizationStatus() == CLAuthorizationStatus.authorizedWhenInUse
|| CLLocationManager.authorizationStatus() == CLAuthorizationStatus.authorizedAlways {
locationManager.requestLocation()
}
else{
locationManager.requestWhenInUseAuthorization()
}
}
else{
//Alert user to open location service, bra bra bra here...
}
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print("error:: \(error)")
}
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
print("didChangeAuthorization")
if status == CLAuthorizationStatus.authorizedWhenInUse
|| status == CLAuthorizationStatus.authorizedAlways {
locationManager.requestLocation()
}
else{
//other procedures when location service is not permitted.
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
print("Did update location called")
// let locValue:CLLocationCoordinate2D = manager.location!.coordinate
// print("locations = \(locValue.latitude) \(locValue.longitude)")
if locations.first != nil {
print("location:: (location)")
}
}

Aaaandd I realized it's b/c I needed to use an Error of a specific type (specifically Swift.Error)
This is the right method declaration for didFailWithError:
func locationManager(_ manager: CLLocationManager, didFailWithError error: Swift.Error) {

Related

How to get location coordinates in macOS、swift

I need to get the geographical coordinates on Mac OS. Here is my code, but an error is reported when running: domain = kclerrordomain code = 0 "(null)"
import Cocoa
import CoreLocation
let locationManager:CLLocationManager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
//设置定位服务管理器代理
locationManager.delegate = self
//设置定位进度
locationManager.desiredAccuracy = kCLLocationAccuracyBest //最佳定位
//更新距离
// locationManager.distanceFilter = 100
//发出授权请求
locationManager.requestAlwaysAuthorization()
if (CLLocationManager.locationServicesEnabled()){
//允许使用定位服务的话,开始定位服务更新
// print("定位开始")
}
}
extension ViewController:CLLocationManagerDelegate{
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
//获取最新的坐标
let currLocation : CLLocation = locations.last! // 持续更新
print("纬度:\(currLocation.coordinate.latitude) 纬度:\(currLocation.coordinate.longitude) 海拔:\(currLocation.altitude) 水平精度:\(currLocation.horizontalAccuracy) 垂直精度:\(currLocation.verticalAccuracy) 方向:\(currLocation.course) 速度:\(currLocation.speed)")
}
func locationManager(_ manager: CLLocationManager,
didChangeAuthorization status: CLAuthorizationStatus) {
print("location manager auth status changed to:" )
switch status {
case .restricted:
print("status restricted")
case .denied:
print("status denied")
case .authorized:
print("已授权")
locationManager.startUpdatingLocation()
case .notDetermined:
print("status not yet determined")
default:
print("unknown state: \(status)")
}
}
func locationManager(_ manager: CLLocationManager,
didFailWithError error: Error) {
print( "location manager failed with error \(error)" )
}
}
enter image description here
When running application:
enter image description here
You need to add location usage description in your info.plist file. After adding your info.plist should look like this .
Add this line in viewDidLoad.
manager.startUpdatingLocation()
Then add the delegate method that updates the location.
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
print(locations.last?.coordinate)
}

locationManager.location is always nil

I have essentially lifted this code from the internet:
//variables
//location manager
var locationManager:CLLocationManager!
var currentLocation:CLLocation?
//outlets
#IBOutlet weak var whatTextField: UITextField!
#IBOutlet weak var whereTextField: UITextField!
#IBOutlet weak var whenTextField: UITextField!
#IBAction func onCreateEventClick(_ sender: Any) {
let event = CAEvent(eventId: "123777abc", eventName: whatTextField.text, location: currentLocation)
event.save { (error) in
//handle event error
print(error)
}
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if( CLLocationManager.authorizationStatus() == .authorizedWhenInUse ||
CLLocationManager.authorizationStatus() == .authorizedAlways){
determineCurrentLocation()
}
}
func determineCurrentLocation() {
locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestWhenInUseAuthorization()
if CLLocationManager.locationServicesEnabled() {
locationManager.startUpdatingLocation()
//locationManager.startUpdatingHeading()
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
currentLocation = locations[0] as CLLocation
// Call stopUpdatingLocation() to stop listening for location updates,
// other wise this function will be called every time when user location changes.
// manager.stopUpdatingLocation()
print("user latitude = \(currentLocation?.coordinate.latitude)")
print("user longitude = \(currentLocation?.coordinate.longitude)")
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error)
{
print("Error \(error)")
}
And at first I was able to see the location (e.g., not nil.). Now however, it is nil every single time. I have tried changing my simulator's location, and I have confirmed that the app in my simulator is sharing location. I also have added a call to startUpdatingLocation() and added the delegate didUpdateLocations and noticed that didUpdateLocationsAny is not called. Any other ideas? Thanks!
Do you call locationManager's method startUpdatingLocation()? The best place to start updating location is locationManager's delegate method:
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
switch(CLLocationManager.authorizationStatus()) {
case .authorizedAlways, .authorizedWhenInUse:
locationManager.startUpdatingLocation()
case .denied, .notDetermined, .restricted:
locationManager.stopUpdatingLocation()
}
}
The location is usually not available immediately after it being requested, once you set your object as the delegate, you should implement func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) and set currentLocation to the last element of that array.
That method will be called whenever the location is acquired or changes.

Google maps - Update User location

I am using Google maps SDK for iOS.
The isMyLocationEnabled is set to true.
Sometimes the use location updated to the right location. But sometimes the location is not updated.
I wanted to know if this option is using the original coordinates of the user? also, there is an option to update the user location? ) I am talking about the blue point.
May be this can help:
import Foundation
import CoreLocation
class Location: NSObject {
static let shared = Location()
var locationManager = CLLocationManager()
func locationManagerSetup() {
// Ask for Authorisation from the User.
locationManager.requestAlwaysAuthorization()
// If location services is enabled get the users location
if CLLocationManager.locationServicesEnabled() {
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestLocation()
locationManager.startUpdatigLocation()
}
}
}
extension Location: CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if let location = locations.first {
// do something
manager.stopUpdatingLocation()
}
else {
manager.requestLocation()
}
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
manager.requestLocation()
}
// If we have been deined access give the user the option to change it
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
if(status == CLAuthorizationStatus.denied) {
// do something
}
}
}

how to execute an action after allow button is pressed in the location access permission?

I am making an app that uses coordinate from GPS, before implementing it, we have to ask permission to the user like the picture above.
I want to make if the user tap "allow" at that alert, then activateGPSToSearchCoordinate() is trigerred, but if 'don't allow' is tapped then I don't want to do anything.
this is my code at the moment, and it doesn't work properly
class LocationManager: NSObject {
let manager = CLLocationManager()
var didGetLocation: ((Coordinate?) -> Void)?
override init() {
super.init()
manager.delegate = self
manager.desiredAccuracy = kCLLocationAccuracyBest
manager.requestLocation()
}
func getPermission() -> CLAuthorizationStatus {
// to ask permission to the user by showing an alert (the alert message is available on info.plist)
if CLLocationManager.authorizationStatus() == .notDetermined {
manager.requestWhenInUseAuthorization()
return .notDetermined
} else if CLLocationManager.authorizationStatus() == .denied {
return .denied
} else if CLLocationManager.authorizationStatus() == .authorizedWhenInUse {
return .authorizedWhenInUse
} else {
return .notDetermined
}
}
}
I will use that class in the view controller method like below, especially that getPermission()
func getCoordinate() {
let coordinateAuthorizationStatus = locationManager.getPermission()
if coordinateAuthorizationStatus == .authorizedWhenInUse {
activateGPSToSearchCoordinate()
} else if coordinateAuthorizationStatus == .denied {
showAlertSetting()
}
}
at the moment, if that permission is triggered for the very first time...
either the user tap 'Allow' or 'don't Allow' the CLAuthorizationStatus will always be .notDetermined
so the activateGPSToSearchCoordinate() , will never be triggered.
so I need to to activate activateGPSToSearchCoordinate() only after the 'Allow' at that alert is pressed
how to solve this problem?
Read more about CLLocationManagerDelegate, there is delegate methods for Success and failure.
public func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
GlobalObjects.shared.latitude = locations[0].coordinate.latitude
GlobalObjects.shared.longtitude = locations[0].coordinate.longitude
GlobalObjects.shared.locationOBJ = locations[0]
print(GlobalObjects.shared.latitude, GlobalObjects.shared.longtitude)
}
public func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
}
What about CLLocationManagerDelegate? Did you try this?
func locationManager(CLLocationManager, didUpdateLocations: [CLLocation])
//Tells the delegate that new location data is available.
func locationManager(CLLocationManager, didFailWithError: Error)
//Tells the delegate that the location manager was unable to retrieve a location value.
func locationManager(CLLocationManager, didFinishDeferredUpdatesWithError: Error?)
//Tells the delegate that updates will no longer be deferred.
func locationManager(CLLocationManager, didUpdateTo: CLLocation, from: CLLocation)
//Tells the delegate that a new location value is available.
Implement CLLocationManagerDelegate, on a class/view controller from where you are calling func getCoordinate().
class TestViewController: CLLocationManagerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
locationManager.delegate = self
}
}
public func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
// get location coordinate
}
public func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
// handle error, if any kind of error occurs
}
Here are nice tutorial with example, may help you, in implementing CLLocationManagerDelegate :
https://developer.apple.com/documentation/corelocation/cllocationmanager
https://www.raywenderlich.com/160517/mapkit-tutorial-getting-started
https://www.appcoda.com/tag/mapkit/
http://www.techotopia.com/index.php/A_Swift_Example_iOS_8_Location_Application

locationManager:didUpdateLocations never called

I have this code in my ViewController:
#IBAction func testButton(sender: UIButton) {
let locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
print("\(CLLocationManager.locationServicesEnabled())")
locationManager.requestWhenInUseAuthorization()
locationManager.startUpdatingLocation()
print("Started updating location")
}
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let userLocation: CLLocation = locations[0]
let long = userLocation.coordinate.longitude
let lat = userLocation.coordinate.latitude
print("\(long), \(lat)")
}
func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
print("Location update failed: \(error)")
}
NSLocationWhenInUseUsageDescription in my plist. It should just work according to all information I could find, but it just outputs
true
Started updating location
Is edit 2 of this question true? If so, what would be the best way to move this out of the viewController?
Before startUpdatingLocation(), have to ask for permission using requestWhenInUseAuthorization() first.
So your codes in ViewController will be similar like the following or you can download a sample project here.
class ViewController: UIViewController, CLLocationManagerDelegate {
let locationManager: CLLocationManager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
self.locationManager.delegate = self
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
self.testButton()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func testButton() {
if CLLocationManager.authorizationStatus() != .AuthorizedWhenInUse {
self.locationManager.requestWhenInUseAuthorization()
return
}
self.locationManager.startUpdatingLocation()
}
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let userLocation: CLLocation = locations[0]
let long = userLocation.coordinate.longitude
let lat = userLocation.coordinate.latitude
print("\(long), \(lat)")
}
func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
print("Location update failed: \(error)")
}
func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
if status == .AuthorizedWhenInUse {
self.testButton()
}
}
}

Resources