Swift 2 CLLocationManager Error updating - cllocationmanager

i updated Xcode 6 to Xcode 7 beta with Swift 2. I get this error and i can't find out how to fix it, please help me. Thanks. This is my code :
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [AnyObject]) {
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: 0.01, longitudeDelta: 0.01))
self.map.setRegion(region, animated: true)
}
and i get this error :
Objective-C method 'locationManager:didUpdateLocations:' provided by method 'locationManager(_:didUpdateLocations:)' conflicts with optional requirement method 'locationManager(_:didUpdateLocations:)' in protocol 'CLLocationManagerDelegate'

Just had the same issue as you, change
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [AnyObject])
to
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation])

Click on your project - go to Build Phases->Link Binary With Libraries and add CoreLocation.framework
import CoreLocation
class ViewController: UIViewController, CLLocationManagerDelegate {
let locationManager = CLLocationManager()
var LatitudeGPS = NSString()
var LongitudeGPS = NSString()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
updateLocation()
func updateLocation() {
self.locationManager.delegate = self
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
//self.locationManager.distanceFilter = 10
self.locationManager.requestWhenInUseAuthorization()
self.locationManager.startUpdatingLocation()
}
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [AnyObject]) {
locationManager.stopUpdatingLocation() // Stop Location Manager - keep here to run just once
LatitudeGPS = String(format: "%.6f", manager.location!.coordinate.latitude)
LongitudeGPS = String(format: "%.6f", manager.location!.coordinate.longitude)
print("Latitude - \(LatitudeGPS)")
}
This is my code which works on xcode 7, also I did have to clean my code (Product->Clean)

You need to mark your class or method with #objc attribute. So either:
#objc class MyManagerDelegate: NSObject, CLLocationManagerDelegate {
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [AnyObject]) {
...
}
}
Or:
class MyManagerDelegate: CLLocationManagerDelegate {
#objc func locationManager(manager: CLLocationManager, didUpdateLocations locations: [AnyObject]) {
...
}
}

I solved this by following code:
//CLLocationManagerDelegate
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [AnyObject]) {
let location:CLLocation = locations[locations.count-1] as! CLLocation
if (location.horizontalAccuracy > 0) {
self.locationManager.stopUpdatingLocation()
print(location.coordinate, terminator: "")
updateWeatherInfo(location.coordinate.latitude, longitude: location.coordinate.longitude)
}
}

func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location = locations.last as! CLLocation!
manager.stopUpdatingLocation()
let region = MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: location.coordinate.latitude, longitude: location.coordinate.longitude), span: MKCoordinateSpan(latitudeDelta: 0.001, longitudeDelta: 0.001))
mapView.setRegion(region, animated: true)
}

Related

Not getting callbacks for Geofence in DidEnter and DidExit methods. Getting error "error: Error Domain=kCLErrorDomain Code=0 "(null)"

class LocationManager: NSObject , ObservableObject {
static var shared = LocationManager()
private var locationManager = CLLocationManager()
#Published var currentLocation : CLLocationCoordinate2D?
#Published var currentRegion : MKCoordinateRegion = MKCoordinateRegion()
#Published var checkInStatus : CheckInOut = .checkOut
override init() {
super.init()
locationManager.delegate = self
locationManager.requestAlwaysAuthorization()
locationManager.requestLocation()
locationManager.startUpdatingLocation()
addGeofence()
if let status = UserDefaults.standard.string(forKey: "status") {
checkInStatus = CheckInOut(rawValue: status) ?? .checkOut
}
}
func addGeofence() {
let region = CLCircularRegion(center: CLLocationCoordinate2D(latitude: 28.5355, longitude: 77.3910), radius: 100, identifier: "Noida")
region.notifyOnEntry = true
region.notifyOnExit = true
if !CLLocationManager.isMonitoringAvailable(for: CLCircularRegion.self) {
print("Geofencing is not supported on this device!")
return
}
locationManager.startMonitoring(for: region)
}
}
extension LocationManager : CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
LocationManager.shared.currentLocation = manager.location?.coordinate
if let loc = LocationManager.shared.currentLocation {
LocationManager.shared.currentRegion = MKCoordinateRegion(center: loc, span: MKCoordinateSpan(latitudeDelta: 0.5, longitudeDelta: 0.5))
}
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print(error.localizedDescription)
}
func locationManager(_ manager: CLLocationManager, monitoringDidFailFor region: CLRegion?, withError error: Error) {
guard let region = region else {
print("Monitoring failed for unknown region")
return
}
print("Monitoring failed for region with identifier: \(region.identifier)")
}
func locationManager(_ manager: CLLocationManager, didEnterRegion region: CLRegion) {
handleEvent(for: region, checkInStatus: .checkIn)
}
func locationManager(_ manager: CLLocationManager, didExitRegion region: CLRegion) {
handleEvent(for: region, checkInStatus: .checkOut)
}
func handleEvent(for region: CLRegion , checkInStatus : CheckInOut) {
Api.hitDummyApi(successHandler: {
DispatchQueue.main.async {
UserDefaultsHelper.saveStatus(status: checkInStatus)
NotificationHandler.createLocalNotificationForCheckInStatus(region: region, checkInStatus: checkInStatus)
}
})
}
}
getting error everytime entering or exiting the region. For sometime the code was running fine but after some time it started showing error. I have checked "allow location simulation" in edit schemes section and added custom location as well.
Also it is working if I change location using Xcode simulation but not if I change using iPhone simulator.

iOS - CLLocation Manager didUpdateLocations being called in one class but not another?

Hi I'm making a program that gets the users location and puts an according annotation on the map. I started by writing all of the code in the View Controller and it gets the location perfectly. Below is the working code in the view controller.
class MapViewController: UIViewController, CLLocationManagerDelegate {
var annotation = MKPointAnnotation()
var userLocation: CLLocation?
#IBOutlet weak var mapView: MKMapView!
var locationManager:CLLocationManager!
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
determineCurrentLocation()
}
func determineCurrentLocation() {
locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestAlwaysAuthorization()
if CLLocationManager.locationServicesEnabled() {
locationManager.startUpdatingLocation()
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
userLocation = locations[0] as CLLocation
print("user latitude = \(userLocation?.coordinate.latitude)")
print("user longitude = \(userLocation?.coordinate.longitude)")
annotation.coordinate = CLLocationCoordinate2D(latitude: (userLocation?.coordinate.latitude)!, longitude: (userLocation?.coordinate.longitude)!)
annotation.title = "You"
mapView.addAnnotation(annotation)
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print("Error \(error)")
}
However now when I try and recreate almost the exact same code in another swift file. didUpdateLocations never gets called. locationManager.startUpdatingLocation() does get called.
Below is my new swift file which I call from the View Controller. Is there any simple concept I'm missing here because I really don't see why this doesn't work.
import Foundation
import CoreLocation
class SendLocation: NSObject, CLLocationManagerDelegate {
var userLocation: CLLocation?
var locationManager:CLLocationManager!
func sendLocationPost() {
determineCurrentLocation()
}
func determineCurrentLocation() {
locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestAlwaysAuthorization()
print("WHY")
if CLLocationManager.locationServicesEnabled(){
locationManager.startUpdatingLocation()
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
userLocation = locations[0] as CLLocation
print("user latitude = \(userLocation?.coordinate.latitude)")
print("user longitude = \(userLocation?.coordinate.longitude)")
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print("Error \(error)")
}
}
I call it using :
let location = SendLocation()
location.sendLocationPost()`
in my View Controller
This happens because you are not keeping a reference to your SendLocation object.
Make SendLocation a property of your UIViewController.
For example, calling it from a static scope will not keep a reference.
WONT WORK:
static func sendLocation() {
let location = SendLocation()
location.sendLocationPost()
}
WILL WORK
let location = SendLocation()
func sendLocation() {
location.sendLocationPost()
}

How to check if locationManager has updated current location?

I would like to show user's current location on startup, and then keep tracking their location but stop centring on the current location. My idea is to centre on the current location in viewDidLoad(), but I don't know how to wait for locationManager to update the current location before centring. Here are the relevant parts of my code:
var currentLocation : CLLocation?
#IBOutlet weak var mapView: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
if CLLocationManager.locationServicesEnabled() {
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.delegate = self
locationManager.requestWhenInUseAuthorization()
locationManager.startUpdatingLocation()
// wait for currentLocation to be updated
animateMap(currentLocation!)
}
mapView.showsUserLocation = true
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
currentLocation = locations.last!
}
func animateMap(_ location: CLLocation) {
let region = MKCoordinateRegionMakeWithDistance(location.coordinate, 1000, 1000)
mapView.setRegion(region, animated: true)
}
You need to simply call that animateMap(currentLocation!) function in delegate method didUpdateLocations where you are initializing the currentLocation.
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
currentLocation = locations.last!
animateMap(currentLocation!)
//Either Call `stop​Updating​Location()`
locationManager.stop​Updating​Location()
//Or you can create one boolean property with default value false and compare it inside this method
if !animatedFlag {
animateMap(currentLocation!)
animatedFlag = true
}
}
var animatedFlag = false
// MARK:- Location lattitude longtitude method Delegate Methods
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation])
{
if locationManager.location != nil
{
let locValue = (locationManager.location?.coordinate)!
lat = locValue.latitude
long = locValue.longitude
}
}
Call the animateMap function in didUpdateLocations delegate method, instead of in viewDidLoad. And, allow the map to center only the first time. You can you some bool variable for that.
var isLocationUpdated = false
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
currentLocation = locations.last!
if (!isLocationUpdated)
{
animateMap(currentLocation!)
isLocationUpdated = true
}
}

CLLocationManager delegate methods are not getting called(google maps is integrated)

The delegate Methods of CLLocationManager
didChangeAuthorizationStatus
and
didUpdateToLocation
are not getting called.
Location Always Usage Description key is already added in info.plist and I am getting notification also when i launch app for the first time.
I am able to see the google map, but i am not able to see current location, When i change location, its not getting updated. Basicaaly delegate methods are not getting called.
//code
import UIKit
import GoogleMaps
class ViewController: UIViewController,GMSMapViewDelegate {
#IBOutlet weak var mapViewTest: GMSMapView!
let locationManager = CLLocationManager()
var currentLocation :CLLocation = CLLocation(latitude: 0.0, longitude: 0.0)
var currentLatitude : Double = 0.0
var currentLongitude : Double = 0.0
override func viewDidLoad()
{
super.viewDidLoad()``
locationManager.delegate = self
if (CLLocationManager.locationServicesEnabled())
{
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.allowsBackgroundLocationUpdates = true
locationManager.requestAlwaysAuthorization()
locationManager.startUpdatingLocation()
}
// Do any additional setup after loading the view, typically from a nib.
}
}
extension ViewController : CLLocationManagerDelegate
{
func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus)
{
if status == .authorizedAlways
{
if(CLLocationManager .locationServicesEnabled())
{
locationManager.startUpdatingLocation()
mapViewTest.isMyLocationEnabled = true
mapViewTest.settings.myLocationButton = true
}
}
}
func locationManager(manager: CLLocationManager, didUpdateToLocation newLocation: CLLocation, fromLocation oldLocation: CLLocation)
{
mapViewTest.camera = GMSCameraPosition(target: (newLocation.coordinate), zoom: 15, bearing: 0, viewingAngle: 0)
currentLocation = newLocation
currentLatitude = newLocation.coordinate.latitude
currentLongitude = newLocation.coordinate.longitude
}
func locationManager(manager: CLLocationManager, didFailWithError error: NSError)
{
print("Errors: " + error.localizedDescription)
}
}
From your code you are working with Swift 3, and in Swift 3 CLLocationManagerDelegate method's signature is changed like this.
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
}
//func locationManager(_ manager: CLLocationManager, didUpdateTo newLocation: CLLocation,
from oldLocation: CLLocation) is deprecated with below one
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
}
Check Apple Documentation on CLLocationManagerDelegate for more details.
After checking your code i found some changes you needs to do as follow,
note : I have only added the code having issue here that of location manager
import UIKit
import CoreLocation
class ViewController: UIViewController {
let locationManager = CLLocationManager()
var currentLocation :CLLocation = CLLocation(latitude: 0.0, longitude: 0.0)
var currentLatitude : Double = 0.0
var currentLongitude : Double = 0.0
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
locationManager.delegate = self
if (CLLocationManager.locationServicesEnabled())
{
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.allowsBackgroundLocationUpdates = true
locationManager.requestAlwaysAuthorization()
locationManager.startUpdatingLocation()
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
extension ViewController : CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
}
func locationManager(_ manager: CLLocationManager, didFinishDeferredUpdatesWithError error: Error?) {
print("Errors: " + (error?.localizedDescription)!)
}
}
Also add below lines in .plist file if not added,
<key>NSLocationWhenInUseUsageDescription</key>
<string>$(PRODUCT_NAME) location use</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>$(PRODUCT_NAME) always uses location </string>
Add these two properties in your info.plist
NSLocationWhenInUseUsageDescription
NSLocationAlwaysUsageDescription
you need to put the mapview delegate to self.
try this:
override func viewDidLoad() {
super.viewDidLoad()
// User Location Settings
locationManager.delegate = self
locationManager.requestWhenInUseAuthorization()
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.startUpdatingLocation()
// Google Maps Delegate
mapView.delegate = self
}
// View will appear
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// Google maps settings
mapView.isMyLocationEnabled = true
mapView.settings.myLocationButton = true
// Get location if autorized
if (CLLocationManager.authorizationStatus() == CLAuthorizationStatus.authorizedWhenInUse) {
let (latitude, longitude) = self.getLocation()
mapView.camera = GMSCameraPosition.camera(
withLatitude: latitude,
longitude: longitude,
zoom: 14)
}
}
//Get the user location
func getLocation() -> (latitude: CLLocationDegrees, longitude: CLLocationDegrees) {
let latitude = (locationManager.location?.coordinate.latitude)!
let longitude = (locationManager.location?.coordinate.longitude)!
return (latitude, longitude)
}

didEnterRegion, didExitRegion not being called

I've been experimenting with region monitoring in order to show an alert or a local notification when the user is within the set region. As a first step, I added a print line to see if it works on the debug area. However, while the other lines are being printed, I'm not getting anything for didEnterRegion and didExitRegion.
I am simulating the location to be in/outside of the given region but I am having no luck. It will be great if someone could look at the code below and see what I've missed. Thank you.
import UIKit
import CoreLocation
class ViewController: UIViewController, CLLocationManagerDelegate {
var manager = CLLocationManager?()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
manager = CLLocationManager()
let latitude: CLLocationDegrees = 48.858400
let longitude: CLLocationDegrees = 2.294500
let center: CLLocationCoordinate2D = CLLocationCoordinate2DMake(latitude, longitude)
let radius: CLLocationDistance = CLLocationDistance(100.0)
let identifier: String = "Notre Dame"
let currRegion = CLCircularRegion(center: center, radius: radius, identifier: identifier)
manager?.distanceFilter = 10
manager?.desiredAccuracy = kCLLocationAccuracyBest
currRegion.notifyOnEntry = true
currRegion.notifyOnExit = true
manager?.requestWhenInUseAuthorization()
manager?.delegate = self
manager?.pausesLocationUpdatesAutomatically = true
manager?.startMonitoringForRegion(currRegion)
manager?.startUpdatingLocation()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func locationManager(manager: CLLocationManager, didStartMonitoringForRegion region: CLRegion) {
print("The monitored regions are: \(manager.monitoredRegions)")
}
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let locValue:CLLocationCoordinate2D = manager.location!.coordinate
print("locations = \(locValue.latitude) \(locValue.longitude)")
}
func locationManager(manager: CLLocationManager, didEnterRegion region: CLRegion) {
NSLog("Entered")
}
func locationManager(manager: CLLocationManager, didExitRegion region: CLRegion) {
NSLog("Exited")
}
}
You can make it work by changing
manager?.requestWhenInUseAuthorization()
to
manager?.requestAlwaysAuthorization()
then add to your info.plist file this key
NSLocationAlwaysUsageDescription with value "This is for testing purpose" or whatever text you want this is what will appear to user requesting to use location

Resources