How do I go about setting the long and latitude value (both which display a when app runs) to a global constant? The values are currently
String(format: "4.4f", latestLocation.coordinate.latitude)
and
String(format: "4.4f", latestLocation.coordinate.longitude)
I want to make these a global constant like userlatitude and userlongitude which can be accessed outside the function. Do I have to return someHope that makes sense.
func locationManager(manager: CLLocationManager!,
didUpdateLocations locations: [AnyObject]!)
{
var latestLocation = locations.last as! CLLocation
latitude.text = String(format: "%.4f",
latestLocation.coordinate.latitude)
longitude.text = String(format: "%.4f",
latestLocation.coordinate.longitude)
}
This way you can store Locations to NSUserDefaults:
//First Convert it to NSNumber.
let lat : NSNumber = NSNumber(double: Location.latitude)
let lng : NSNumber = NSNumber(double: Location.longitude)
//Store it into Dictionary
let locationDict = ["lat": lat, "lng": lng]
//Store that Dictionary into NSUserDefaults
NSUserDefaults.standardUserDefaults().setObject(locationDict, forKey: "Location")
After that you can access it this way anywhere you want:
//Access that stored Values
let userLoc = NSUserDefaults.standardUserDefaults().objectForKey("Location") as! [String : NSNumber]
//Get user location from that Dictionary
let userLat = userLoc["lat"]
let userLng = userLoc["lng"]
var Annotation = MKPointAnnotation()
Annotation.coordinate.latitude = userLat as! CLLocationDegrees //Convert NSNumber to CLLocationDegrees
Annotation.coordinate.longitude = userLng as! CLLocationDegrees //Convert NSNumber to CLLocationDegrees
One solution could be that you store the values as NSUserDefaults, which gives you access to the values when you need it. try this link for more information http://www.codingexplorer.com/nsuserdefaults-a-swift-introduction/
Define your Variable Below of import statement. Something Like,
import UIKit
let latitude = 4.0
// Do Stuff - This Variable access in Any class. Thanx Swift....
Another solution is put your value in .plist/NSUser Default and access in every class(Where should you wish to use) using appropriate key.
Related
I'm trying to save the coordinates of a user while in one ViewController so that it can be used to create an Annotation that can displayed in another ViewController.
In the view controller that stores the coordinates I'm using the code
NSUserDefaults.standardUserDefaults().setObject( Location, forKey: "Location")
In the map view controller that displays the annotation I'm trying to get the coordinates using the code
let Location = NSUserDefaults.standardUserDefaults().stringForKey("Location")
var Annotation = MKPointAnnotation()
Annotation.coordinate = Location
It is telling me that the value of type String? to a value of type CLLocationCoordinate2D.
So how do I convert the CLLocationCoordinate2D coordinates into a value of type String?
This way you can store Locations to NSUserDefaults:
//First Convert it to NSNumber.
let lat : NSNumber = NSNumber(double: Location.latitude)
let lng : NSNumber = NSNumber(double: Location.longitude)
//Store it into Dictionary
let locationDict = ["lat": lat, "lng": lng]
//Store that Dictionary into NSUserDefaults
NSUserDefaults.standardUserDefaults().setObject(locationDict, forKey: "Location")
After that you can access it this way:
//Access that stored Values
let userLoc = NSUserDefaults.standardUserDefaults().objectForKey("Location") as! [String : NSNumber]
//Get user location from that Dictionary
let userLat = userLoc["lat"]
let userLng = userLoc["lng"]
var Annotation = MKPointAnnotation()
Annotation.coordinate.latitude = userLat as! CLLocationDegrees //Convert NSNumber to CLLocationDegrees
Annotation.coordinate.longitude = userLng as! CLLocationDegrees //Convert NSNumber to CLLocationDegrees
UPDATE:
HERE is your Example project.
extension CLLocationCoordinate2D:Printable
{
init(coords : String)
{
var fullNameArr = split(coords) {$0 == ";"}
self.latitude = NSNumberFormatter().numberFromString(fullNameArr[0])!.doubleValue
self.longitude = (fullNameArr.count > 1) ? NSNumberFormatter().numberFromString(fullNameArr[1])!.doubleValue : 0
}
public var description : String
{
return "\(self.latitude);\(self.longitude)"
}
}
Then use as in your sample code :
var coord = CLLocationCoordinate2D(latitude: 3.2, longitude: 6.4)
NSUserDefaults.standardUserDefaults().setObject(coord.description, forKey: "Location")
var readedCoords = CLLocationCoordinate2D(coords: NSUserDefaults.standardUserDefaults().stringForKey("Location")!)
You can store the latitude or the longitude (or both in a dictionary or a tuple). The way to wrap them in String:
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
var locValue:CLLocationCoordinate2D = manager.location!.coordinate
var lat : String = locValue.latitude.description
var lng : String = locValue.longitude.description
//do whatever you want with lat and lng
}
Using an sprint kind of formatting:
func Coord2String(location : CLLocationCoordinate2D) -> String {
return String(format : "latitude : %f, longitude : %f", location.latitude, location.longitude)
}
I want to save location coordinates into Core Data- what is the right way of storing these and retrieving them?
At the moment I am doing this and getting errors:
var newPlaceCoordinate = CLLocationCoordinate2D()
var newPlaceLatitude = CLLocationDegrees()
var newPlaceLongitude = CLLocationDegrees()
I get my coordinates from using Google maps API using the autocomplete widget.
let newPlaceCoordinate = place.coordinate
self.newPlaceCoordinate = place.coordinate
let newPlaceLatitude = place.coordinate.latitude
print(newPlaceLatitude)
self.newPlaceLatitude = place.coordinate.latitude
let newPlaceLongitude = place.coordinate.longitude
print(newPlaceLongitude)
self.newPlaceLongitude = place.coordinate.longitude
Then to store the coordinates I use:
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context = appDelegate.persistentContainer.viewContext
let newPlace = NSEntityDescription.insertNewObject(forEntityName: "StoredPlace", into: context)
newPlace.setValue(newPlaceCoordinate, forKey: "coordinate")
newPlace.setValue(newPlaceLatitude, forKeyPath: "latitude")
newPlace.setValue(newPlaceLongitude, forKeyPath: "longitude")
And I have the attributes all set as String types.
Then to retrieve in my ViewDidLoad I have:
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context = appDelegate.persistentContainer.viewContext
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "StoredPlace")
request.returnsObjectsAsFaults = false
if let coordinate = result.value(forKey: "coordinate") as? String
{
let latitude = (coordinate as NSString).doubleValue
let longitude = (coordinate as NSString).doubleValue
let markers = GMSMarker()
markers.position = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
markers.icon = GMSMarker.markerImage(with: UIColor.yellow)
markers.tracksViewChanges = true
markers.map = vwGMap
}
So this is not working and producing an error of 'attribute: property = "coordinate"; desired type = NSString; given type = NSConcreteValue'. I have a few questions.
How do I save a coordinate data appropriately?
Do I save it as a CLLocationDegrees or CLLocationCoordinate2D?
How do I convert these objects into NSString or should I be using a different type in my attributes? (I tried changing it to Double or Integer but it also produced errors). I have multiple location coordinates which I would want to store and retrieve from core data.
If you are going to deal with lots of data, then CoreData is the best bet.
These are my attributes in StorePlace entity, its best to save only latitude and longitude and create coordinates from them when needed in your implementation.
#NSManaged public var newPlaceLatitude: Double
#NSManaged public var newPlaceLongitude: Double
And to insert new data, I will do
class func insert(latitude: Double, longitude: Double) {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let managedObjectContext = appDelegate.managedObjectContext
let entity = NSEntityDescription.entity(forEntityName: "StoredPlace", in:managedObjectContext)
let newItem = StoredPlace(entity: entity!, insertInto: managedObjectContext)
newItem.newPlaceLatitude = latitude
newItem.newPlaceLongitude = longitude
do {
try managedObjectContext.save()
} catch {
print(error)
}
}
After retrieving latitude, longitude you can use coordinate in your implementations as
let newItem = getCoordinateFromCoreData() // your retrieval function
let coordinate = CLLocationCoordinate2D(latitude: newItem.latitude, longitude: newItem.longitude)
You need to convert the co-ordinate to double/NSdata type and then store it in CoreData. Use NSKeyedArchiver and NSKeyedUnarchiver to store and retrieve the values. CoreData can't store CLLocation object directly.
// Convert CLLocation object to Data
let newPlaceLatitudeArchived = NSKeyedArchiver.archivedDataWithRootObject(newPlaceLatitude)
//CoreData Piece
newPlace.setValue(newPlaceLatitudeArchived, forKeyPath: "latitude")
// fetch the latitude from CoreData as Archive object and pass it to unarchive to get the CLLocation
let newPlaceLatitudeUnArchived = NSKeyedUnarchiver.unarchiveObjectWithData(archivedLocation) as? CLLocation
You will need to convert you attribute to binary type in CoreData in this case.
I had been struggling to store CLLocationCoordinate2D data from markers on a google maps to CoreData. This cannot be done directly but I found a work around where I take the coordinates, split into CLLocationDegrees, convert it into a string text and store it. I do this by the following:
let marker = GMSMarker()
marker.position = CLLocationCoordinate2DMake(place.coordinate.latitude, place.coordinate.longitude)
let newPlaceLatitude = place.coordinate.latitude
print(newPlaceLatitude)
var latitudeText:String = "\(newPlaceLatitude)"
self.latitudeText = "\(newPlaceLatitude)"
let newPlaceLongitude = place.coordinate.longitude
print(newPlaceLongitude)
var longitudeText:String = "\(newPlaceLongitude)"
self.longitudeText = "\(newPlaceLongitude)"
Storing into CoreData:
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context = appDelegate.persistentContainer.viewContext
let newPlace = NSEntityDescription.insertNewObject(forEntityName:
"StoredPlace", into: context)
newPlace.setValue(latitudeText, forKeyPath: "latitude")
newPlace.setValue(longitudeText, forKeyPath: "longitude")
However now I am struggling to reconstruct the strings back into CLLocationCoordinates. How would I turn a string to a CLLocationDegree/CLLocationCoordinate2D ? This is supposedly pretty simple but I have found that the following method doesn't work:
let latitude: CLLocationDegrees = Double(latitudeText)!
let longitude: CLLocationDegrees = Double(longitudeText)!
let markers = GMSMarker()
print(latitude)
print(longitude)
markers.position = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
any other suggestions about how to change string to coordinate?
CLLocation's latitude and longitude are doubles, so with that in mind, you might consider having latitude and longitude properties that are doubles on your StoredPlace object. I called the properties coordinateX and coordinateY so it's easier to remember that they're custom coordinates, not "factory" properties.
You could create an extension in a file called StoredPlace+Extension.swift that looks like this:
import CoreData
import CoreLocation
extension StoredPlace {
func location() -> CLLocation {
let location = CLLocation(latitude: self.coordinateX, longitude: self.coordinateY)
return location
}
}
With this extension, you can then get the coordinates out of your results as follows:
for result in results {
print("coordinate = \(result.location().coordinate)")
print("latitude = \(result.location().coordinate.latitude)")
print("longitude = \(result.location().coordinate.longitude)")
}
You need to typecast your lat and long in decimal values, more preferable is double instead of float because of precision value which can drop pins at perfect locations.
Type casting in double using as keyword:
(yourCordinateString as NSString).doubleValue
casting in float values:
(yourCordinateString as NSString).floatValue
let latitude = NSUserDefaults .standardUserDefaults().valueForKey(klat) as! Double
let longitude = NSUserDefaults .standardUserDefaults().valueForKey(klong) as! Double
let location:CLLocationCoordinate2D = CLLocationCoordinate2DMake(latitude, longitude)
//Second Location lat and long
let latitudeSec:CLLocationDegrees = 11.0100
let longitudeSec:CLLocationDegrees = 77.3620
let locationSec:CLLocationCoordinate2D = CLLocationCoordinate2DMake(latitudeSec, longitudeSec)
let span:MKCoordinateSpan = MKCoordinateSpanMake(1, 1)
let region:MKCoordinateRegion = MKCoordinateRegionMake(location, span)
mapView.setRegion(region, animated: true)
let myAn1 = MyAnnotation(title: "Office", coordinate: location,subtitle: "MyOffice");
I am unable to retrieve the map locations here which I have stored in the app earlier using NSUserDefaults in the keyword "klat and "klong" It shows the following error:
"Could not cast value of type '__NSCFString' (0x1604da4) to 'NSNumber' (0x971800)"
Use following code for storing the latitude and longitude
[[NSUserDefaults standardUserDefaults] setDouble:latitude forKey:klat]
[[NSUserDefaults standardUserDefaults] setDouble:longitude forKey:klong]
And for retrieving
let latitude = NSUserDefaults.standardUserDefaults().doubleForKey(klat)
let latitude = NSUserDefaults.standardUserDefaults().doubleForKey(klong)
I'm trying to save the coordinates of a user while in one ViewController so that it can be used to create an Annotation that can displayed in another ViewController.
In the view controller that stores the coordinates I'm using the code
NSUserDefaults.standardUserDefaults().setObject( Location, forKey: "Location")
In the map view controller that displays the annotation I'm trying to get the coordinates using the code
let Location = NSUserDefaults.standardUserDefaults().stringForKey("Location")
var Annotation = MKPointAnnotation()
Annotation.coordinate = Location
It is telling me that the value of type String? to a value of type CLLocationCoordinate2D.
So how do I convert the CLLocationCoordinate2D coordinates into a value of type String?
This way you can store Locations to NSUserDefaults:
//First Convert it to NSNumber.
let lat : NSNumber = NSNumber(double: Location.latitude)
let lng : NSNumber = NSNumber(double: Location.longitude)
//Store it into Dictionary
let locationDict = ["lat": lat, "lng": lng]
//Store that Dictionary into NSUserDefaults
NSUserDefaults.standardUserDefaults().setObject(locationDict, forKey: "Location")
After that you can access it this way:
//Access that stored Values
let userLoc = NSUserDefaults.standardUserDefaults().objectForKey("Location") as! [String : NSNumber]
//Get user location from that Dictionary
let userLat = userLoc["lat"]
let userLng = userLoc["lng"]
var Annotation = MKPointAnnotation()
Annotation.coordinate.latitude = userLat as! CLLocationDegrees //Convert NSNumber to CLLocationDegrees
Annotation.coordinate.longitude = userLng as! CLLocationDegrees //Convert NSNumber to CLLocationDegrees
UPDATE:
HERE is your Example project.
extension CLLocationCoordinate2D:Printable
{
init(coords : String)
{
var fullNameArr = split(coords) {$0 == ";"}
self.latitude = NSNumberFormatter().numberFromString(fullNameArr[0])!.doubleValue
self.longitude = (fullNameArr.count > 1) ? NSNumberFormatter().numberFromString(fullNameArr[1])!.doubleValue : 0
}
public var description : String
{
return "\(self.latitude);\(self.longitude)"
}
}
Then use as in your sample code :
var coord = CLLocationCoordinate2D(latitude: 3.2, longitude: 6.4)
NSUserDefaults.standardUserDefaults().setObject(coord.description, forKey: "Location")
var readedCoords = CLLocationCoordinate2D(coords: NSUserDefaults.standardUserDefaults().stringForKey("Location")!)
You can store the latitude or the longitude (or both in a dictionary or a tuple). The way to wrap them in String:
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
var locValue:CLLocationCoordinate2D = manager.location!.coordinate
var lat : String = locValue.latitude.description
var lng : String = locValue.longitude.description
//do whatever you want with lat and lng
}
Using an sprint kind of formatting:
func Coord2String(location : CLLocationCoordinate2D) -> String {
return String(format : "latitude : %f, longitude : %f", location.latitude, location.longitude)
}