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??
Related
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()
}
I have two different classes, one of them, LocationService, is just for determining location. Problem is that I don't know why it doesn't update coordinates variable.
ViewController:
import UIKit
class ViewController: UIViewController {
var coords: (lat: Double, long: Double) = (0,0)
var tracking = LocationServices()
override func viewDidLoad() {
super.viewDidLoad()
tracking.startTracking()
tracking.getLocations()
coordinat = tracking.coordinates
retreiveWeatherForecast()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// retrieveWeatherForecast functions
And simple locationService class:
import UIKit
import CoreLocation
class LocationServices: NSObject, CLLocationManagerDelegate {
var locationManager = CLLocationManager()
var coordinates: (lat: Double, long: Double) = (0,0)
func startTracking() {
locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestAlwaysAuthorization()
locationManager.startUpdatingLocation()
}
func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
locationManager.stopUpdatingLocation()
print(error)
}
func getLocations() {
#if os (ios)
func locationManager(manager:CLLocationManager, didUpdateLocations locations:[AnyObject]) {
//println("locations = \(locationManager)")
var latValue = locationManager.location.coordinate.latitude
var lonValue = locationManager.location.coordinate.longitude
coordinates = (latValue,lonValue)
println(latValue)
println(lonValue)
}
#endif
}
}
When I build it, it returns weather with default coordinates = (0,0).
Well, I accidentally made it work. As far as I understand problem was here: func locationManager(manager:CLLocationManager, didUpdateLocations locations:[AnyObject]) locations must be of CLLocation type, not AnyObject.
I'm using Swift 2.0.
I am getting the users current location and dropping this as a println(). The idea is that I am going to hit a button to get the new location, however currently the app keeps updating constantly (every second) instead. I have tried moving the getLocation() function inside my IBAction but that crashed the thing. I have updated the info.plist so thats not a problem. Heres le code:
import UIKit
import CoreLocation
class ViewController: UIViewController, CLLocationManagerDelegate{
#IBOutlet var latitude : UILabel!
#IBOutlet var longitude : UILabel!
var locationManager = CLLocationManager()
var startLocation: CLLocation!
override func viewDidLoad() {
super.viewDidLoad()
locationManager = CLLocationManager()
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.delegate = self
locationManager.requestWhenInUseAuthorization()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func findMyLocation(sender: AnyObject){
startLocation = nil
locationManager.startUpdatingLocation()
}
func getLocation(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!){
var userLocation:AnyObject = locations[0] as! CLLocation
var strlat = String(format: "%.4f", userLocation.coordinate.latitude)
var strlong = String(format: "%.4f",userLocation.coordinate.longitude)
latitude.text = String(format: "%.4f", userLocation.coordinate.latitude)
longitude.text = String(format: "%.4f",userLocation.coordinate.longitude)
println("latitude: " + strlat)
println("longitide: " + strlong)
if startLocation == nil {
startLocation = userLocation as! CLLocation
locationManager.stopUpdatingLocation()
}
}
func locationManager(manager: CLLocationManager!,
didFailWithError error: NSError!) {
}
}
Move the locationManager.startUpdatingLocation() to your findMyLocation function. This will start the locationManager when your button is pressed and begin calling the didUpdateLocations Inside your if startLocation == nil add locationManager.stopUpdatingLocation() this will stop the locationManager after you have set your startLocation var. Every time the user presses the button the process will run again.
One additional note, you should add more code into the didUpdateLocations to check the accuracy and timestamp of the location before you use it as it may not be a valid/accurate location for what you are trying to do.
UPDATE:
Had a chance to validate and the code will work with the changes suggested. Here is what your final code should look like. I am also assuming you have set your plist entries for locations services and your simulator is set to simulate locaitons.
import UIKit
import CoreLocation
class ViewController: UIViewController, CLLocationManagerDelegate{
#IBOutlet var latitude : UILabel!
#IBOutlet var longitude : UILabel!
var locationManager : CLLocationManager! = CLLocationManager()
var startLocation: CLLocation!
override func viewDidLoad() {
super.viewDidLoad()
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.delegate = self
locationManager.requestWhenInUseAuthorization()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func findMyLocation(sender: AnyObject){
startLocation = nil
locationManager.startUpdatingLocation()
}
func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!){
var userLocation:AnyObject = locations[0] as! CLLocation
var strlat = String(format: "%.4f", userLocation.coordinate.latitude)
var strlong = String(format: "%.4f",userLocation.coordinate.longitude)
latitude.text = String(format: "%.4f", userLocation.coordinate.latitude)
longitude.text = String(format: "%.4f",userLocation.coordinate.longitude)
println("latitude: " + strlat)
println("longitide: " + strlong)
if startLocation == nil {
startLocation = userLocation as! CLLocation
locationManager.stopUpdatingLocation()
}
}
func locationManager(manager: CLLocationManager!, didFailWithError error: NSError!) {
println("error with location manager: " + error.description)
}
}
I am trying to use CoreLocation to get the latitude and longitude coordinates in iOS 8. After looking through a lot of posts, I am still unsure how to go about doing this. Also, I would appreciate a brief explanation of the locationManager() methods as I don't understand what role they play in obtaining the location. Do I ever need to call these methods? Because I never saw them called in any examples.
class ViewController: UIViewController, CLLocationManagerDelegate {
var locationMan = CLLocationManager()
var ourLocation: CLLocation!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.locationMan.delegate = self
self.locationMan.desiredAccuracy = kCLLocationAccuracyBest
self.locationMan.requestWhenInUseAuthorization()
self.locationMan.startUpdatingLocation()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func locationManager(manager: CLLocationManager!, didUpdateLocations locations : [AnyObject]!){
locationMan.stopUpdatingLocation()
ourLocation = locations[0] as! CLLocation
}
func locationManager(manager: CLLocationManager!, didFailWithError error: NSError!) {
println("Error: " + error.localizedDescription)
}
#IBAction func button(sender: AnyObject) {
var testClass:item = item()
After the next line, the app crashes and I get the error: fatal error: unexpectedly found nil while unwrapping an Optional value. I think this means that ourLocation never actually gets set. (Note that I am casting to float because I need to store the location as a float on my server)
testClass.lat = Float(ourLocation.coordinate.latitude)
println(testClass.lat)
testClass.long = Float(ourLocation.coordinate.longitude)
println(testClass.long)
testClass.name = "Nice"
testClass.description = "Wow this is pretty cool"
testClass.postItemToServer()
}
}
Note that I have updated my plist file appropriately! Location is turned on in the simulator.
Check if the values you are passing to variable are nil or not
if ourLocation.coordinate.latitude != nil
{
testClass.lat = Float(ourLocation.coordinate.latitude)
println(testClass.lat)
}
Also check for longitude.
import UIKit
import CoreLocation
class ViewController: UIViewController, CLLocationManagerDelegate{
var manager:CLLocationManager!
var location : CLLocation!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.manager = CLLocationManager()
self.manager.delegate = self;
self.manager.desiredAccuracy = kCLLocationAccuracyBest
self.manager.requestWhenInUseAuthorization()
self.manager.startUpdatingLocation()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func locationManager(manager: CLLocationManager!, didUpdateLocations locations : [AnyObject]!){
manager?.stopUpdatingLocation()
self.location = locations[0] as CLLocation
}
func locationManager(manager: CLLocationManager!, didFailWithError error: NSError!) {
println("Error: " + error.localizedDescription)
}
#IBAction func button(sender: AnyObject) {
//check if location is not nil
if self.location != nil {
//assign your loaction values here
let lat = Float(location.coordinate.latitude)
let long = Float(location.coordinate.longitude)
} else {
println("locationManager.location is nil")
}
}
}
The location property is an implicitly unwrapped CLLocation optional, and it is likely nil. You should never access members of implicitly unwrapped optional unless you know it is not nil.
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.