Trying to find users location in Xcode with Swift on starting the app but having optional error? - ios

I'm attempting to have the app find the user's location once the app has been started. However, I continually find an error in the viewDidLoad method as I try to requestWhenInUseAuthorization and I receive the following error:
fatal error: unexpectedly found nil while unwrapping an Optional value (lldb)
I would be really grateful if anyone could help me find a solution to this problem. Thanks!
class ViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {
#IBOutlet weak var mapView: MKMapView!
var lastLocation = CLLocation()
var locationAuthorizationStatus:CLAuthorizationStatus!
var window: UIWindow?
let locationManager: CLLocationManager!
var seenError : Bool = false
var locationFixAchieved : Bool = false
var locationStatus : NSString = "Not Started"
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
self.initLocationManager()
}
override func viewDidLoad() {
super.viewDidLoad()
if (CLLocationManager.locationServicesEnabled()) {
seenError = false
locationFixAchieved = false
locationManager = CLLocationManager()
self.initLocationManager()
locationManager.requestWhenInUseAuthorization()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.startUpdatingLocation()
}
mapView.showsUserLocation = true
mapView.delegate = self
self.mapView.setUserTrackingMode(MKUserTrackingMode.Follow, animated: true);
}
// Location Manager helper stuff
func initLocationManager() {
locationManager.requestWhenInUseAuthorization()
}
// Location Manager Delegate stuff
func locationManager(manager: CLLocationManager!, didFailWithError error: NSError!) {
locationManager.stopUpdatingLocation()
if ((error) != nil) {
if (seenError == false) {
seenError = true
print(error)
}
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}

Your didload method is getting called before the didAppear method. Therefore, your location manager is not initialized yet. So you need to initialize it before using it.

Related

CLLocationManager() Location is nil in simulator

I'm try to get latitude and longitude but location is always nil.
class FinalizeOrderController: UIViewController {
var locManager = CLLocationManager()
var currentLocation: CLLocation!
override func viewDidLoad() {
super.viewDidLoad()
currentLocation = CLLocation()
locManager.requestWhenInUseAuthorization()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func FinaliseOrder(_ sender: Any) {
if (CLLocationManager.authorizationStatus() == CLAuthorizationStatus.authorizedWhenInUse ||
CLLocationManager.authorizationStatus() == CLAuthorizationStatus.authorizedAlways) {
currentLocation = locManager.location
print(locManager.location?.coordinate.latitude) //prints nil
print(currentLocation.coordinate.longitude) //fatal error: unexpectedly found nil while unwrapping an Optional value
}
lbl1.text = "\(currentLocation.coordinate.longitude)"
lbl2.text = "\(currentLocation.coordinate.latitude)"
}
I add info.plist keys and run simulator location from Xcode and chooses simulator location from debug but no way always nil
Try this :
var locationManager: CLLocationManager?
var currentLocation:CLLocation?
Conform Delegate
class ViewController: UIViewController,CLLocationManagerDelegate
In ViewDidLoad
override func viewDidLoad() {
super.viewDidLoad()
locationManager = CLLocationManager();
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest
let authorizationStatus = CLLocationManager.authorizationStatus()
if (authorizationStatus == CLAuthorizationStatus.NotDetermined) {
locationManager.requestWhenInUseAuthorization()
} else {
locationManager.startUpdatingLocation()
}
}
In Delegate
func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {
currentLocation = locations[locations.count-1] as CLLocation
print("locations = \(currentLocation)")
// lbl1.text = "\(currentLocation.coordinate.latitude)";
// lbl2.text = "\(currentLocation.coordinate.longitude)";
}
In button action
#IBAction func FinaliseOrder(_ sender: Any) {
lbl1.text = "\(currentLocation.coordinate.longitude)"
lbl2.text = "\(currentLocation.coordinate.latitude)"
}

Making an app using swift that gets user's location

I ran my code for getting the user's location and this is the error I get. Can someone please help me figure it out?
My code is as follows:
import UIKit
import CoreLocation
class ViewController: UIViewController, CLLocationManagerDelegate {
#IBOutlet weak var citybtn: UIButton!
#IBOutlet weak var citylbl: UILabel!
let locationManager = CLLocationManager()
var currentLocation : CLLocation!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
// Used to start getting the users location
//let locationManager = CLLocationManager()
// For use when the app is open
//locationManager.requestAlwaysAuthorization()
// If location services is enabled get the users location
//if CLLocationManager.locationServicesEnabled() {
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest // You can change the locaiton accuary here.
locationManager.requestWhenInUseAuthorization()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(true)
locationAuthStatus()
}
func locationAuthStatus() {
if CLLocationManager.authorizationStatus() == .authorizedWhenInUse {
currentLocation = locationManager.location
print(currentLocation.coordinate.latitude)
print(currentLocation.coordinate.longitude)
} else {
locationManager.requestWhenInUseAuthorization()
locationAuthStatus()
}
}
#IBAction func buttonpresses(_ sender: Any) {
}
}
sounds like you did not enable the location update capability of your target:
choose target
select capabilities
in Background Modes, tick Location updates

Getting location using another class not working when calling function swift

I was using the ViewController class before to get the users updates but now when expanding the application i needed to move it to another class that simply handles all the location updates. Here is the code that i am using now:
class ViewController: UIViewController, UITextFieldDelegate {
#IBAction func pickMeUpButton(sender: AnyObject) {
sendPushNotificationController().sendPushNotification("sendRequest",userLat: defaults.stringForKey("userLat")!, userLong: defaults.stringForKey("userLong")! )
}
#IBOutlet var numberForPickup: UITextField!
let defaults = NSUserDefaults.standardUserDefaults()
override func viewDidLoad() {
super.viewDidLoad()
self.numberForPickup.delegate = self
getLocationController().initLocation()
}
So i made another class called getLocationController with an init function that should start the location updates. Here is the code:
class getLocationController: UIViewController, CLLocationManagerDelegate {
var locationManager: CLLocationManager!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func initLocation(){
print("Im in here")
locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestAlwaysAuthorization()
locationManager.startUpdatingLocation()
}
func locationManager(manager: CLLocationManager, didUpdateToLocation newLocation: CLLocation, fromLocation oldLocation: CLLocation) {
print("In location")
if UIApplication.sharedApplication().applicationState == .Active {
print("App in Foreground")
}else {
let Device = UIDevice.currentDevice()
let iosVersion = Double(Device.systemVersion) ?? 0
let iOS9 = iosVersion >= 9
if iOS9{
locationManager.allowsBackgroundLocationUpdates = true;
locationManager.pausesLocationUpdatesAutomatically = false;
}
//let iOS7 = iosVersion >= 7 && iosVersion < 8
print("App is backgrounded. New location is %#", newLocation)
}
}
}
Now the print in initLocation is printed but not the print in didUpdateLocations. I used the very same code in ViewController class and it worked perfectly fine. Now when i am trying to move it to another class that is now really a view on the phone but simply a helper class its not working. Any ideas why?
I don't see you assigning the getLocationController to a variable anywhere in the ViewController. That means the getLocationController would go out of scope and be destroyed, wouldn't it? That would explain why the callback didUpdateToLocation isn't called.
Try:
class ViewController: UITextFieldDelegate {
#IBAction func pickMeUpButton(sender: AnyObject) {
sendPushNotificationController().sendPushNotification("sendRequest",userLat: defaults.stringForKey("userLat")!, userLong: defaults.stringForKey("userLong")! )
}
#IBOutlet var numberForPickup: UITextField!
let defaults = NSUserDefaults.standardUserDefaults()
var glc:getLocationController // is this how it is in Swift?!
override func viewDidLoad() {
super.viewDidLoad()
self.numberForPickup.delegate = self
glc = getLocationController()
glc.initLocation()
}

IOS 8 swift CoreLocation

Im learning Xcode 6.3 and swift and following a book from apress Beginning Xcode with swift, in chapter 4 when doing the first tab for the location tracker it shows nothing at all and I'm confused. The code for the first tab is this
import UIKit
import CoreLocation
class TrackViewController: UIViewController, CLLocationManagerDelegate {
var locationManager: CLLocationManager!
#IBOutlet weak var locationText: UITextView!
#IBOutlet weak var toggleSwitch: UISwitch!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func changeToggle(sender: UISwitch) {
if toggleSwitch.on {
self.locationText.text = " "
if (CLLocationManager.locationServicesEnabled() == false) {
self.toggleSwitch.on = false
}
if locationManager == nil {
locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.distanceFilter = 10.0
locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
locationManager.requestWhenInUseAuthorization()
UIApplication.sharedApplication().cancelAllLocalNotifications()
NSLog("location is on supposely")
}
locationManager.startUpdatingLocation()
} else {
if locationManager != nil {
locationManager.stopUpdatingLocation()
}
}
}
func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {
var location: CLLocation = locations[locations.endIndex - 1] as! CLLocation
self.locationText.text = location.description
}
func locationManager(manager: CLLocationManager!, didFailWithError error: NSError!) {
locationText.text = "failed with error \(error.description)"
}
}
I have activated in the simulator the location services and in info.plist added the NSLocationWhenInUsageDescription and the Privacy - Location..., but nothing happens when toggling the switch I get no feedback that something is on. Any help??

CLLocationManagerDelegate not catching events

first of all, i'm new to iOS development, so please don't explain to me with objective-c examples.
my question is:
i've made this class:
import UIKit
import CoreLocation
class BeaconRadar: NSObject, CLLocationManagerDelegate {
var manager : CLLocationManager!
var region : CLBeaconRegion!
var seenError = false
var locationFixAchieved = false
var locationStatus = "Not Started"
init() {
super.init()
var major = CLBeaconMajorValue( 10 )
var uuid = NSUUID( UUIDString: "E2C56DB5-DFFB-48D2-B060-D0F5A71096E0" )
var id = "test"
manager = CLLocationManager()
region = CLBeaconRegion( proximityUUID: uuid, major: major, identifier: id )
manager.delegate = self
manager.desiredAccuracy = kCLLocationAccuracyBest
manager.requestAlwaysAuthorization()
manager.startRangingBeaconsInRegion(region)
}
func locationManager(manager: CLLocationManager!, didRangeBeacons beacons: AnyObject[], inRegion region: CLBeaconRegion! ){
if (locationFixAchieved == false) {
locationFixAchieved = true
println(beacons)
}
}
// If failed
func locationManager(_manager: CLLocationManager!, rangingBeaconsDidFailForRegion region: CLBeaconRegion!, withError error: NSError!){
manager.stopUpdatingLocation()
if (error) {
if (seenError == false) {
seenError = true
println("Error getting location")
}
}
}
// // authorization status
func locationManager(_manager: CLLocationManager!, didChangeAuthorizationStatus status: CLAuthorizationStatus){
println("2")
var shouldIAllow = false
switch status {
case CLAuthorizationStatus.Restricted:
locationStatus = "Restricted Access"
case CLAuthorizationStatus.Denied:
locationStatus = "User denied access"
case CLAuthorizationStatus.NotDetermined:
locationStatus = "Status not determined"
default:
locationStatus = "Allowed Access"
shouldIAllow = true
}
NSNotificationCenter.defaultCenter().postNotificationName("LabelHasbeenUpdated", object: nil)
if (shouldIAllow == true) {
println("Location Allowed")
// Start location services
manager.startUpdatingLocation()
} else {
println("Denied access: \(locationStatus)")
}
}
}
and my viewController is:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
var location = BeaconRadar()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
i'm expecting to get one of the messages in the implemantation func for the authorization status. ( the last one in BeaconRadar). but i'm getting nothing.
if i'll implement all this methods in the viewController instead of in new class
(i.e:
class ViewController: UIViewController, CLLocationManagerDelegate {
.....
}
then it will work just fine...
Am i missing something?
You have declared your BeaconRadar instance as a local variable inside viewDidLoad, so as soon as this function exits, the BeaconRadar instance is released.
You should move the BeaconRegion variable out of the function -
class ViewController: UIViewController {
let location = BeaconRadar()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}

Resources