Converting Parse GeoPoint into a CLLocation in Swift - ios

I am working in Swift.
In my Parse backend I have a key called locations which has a number of geoPoint values of which are latitude and longitude points. I want to query/fetch all these points and place them into an array so I can then use them as different annotations on a map.
I am having trouble querying the locations so that they can be used as a CLLocation for the map.
If anyone could help me do this it would be much appreciated.

You can create a variable as a PFGeoPoint and you can put your data from parse into this variable:
var descLocation: PFGeoPoint = PFGeoPoint()
var innerP1 = NSPredicate(format: "ObjectID = %#", objectID)
var innerQ1:PFQuery = PFQuery(className: "Test", predicate: innerP1)
var query = PFQuery.orQueryWithSubqueries([innerQ1])
query.addAscendingOrder("createdAt")
query.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]!, error: NSError!) -> Void in
if error == nil {
for object in objects {
descLocation = object["GeoPoint"] as PFGeoPoint
}
} else {
println("Error")
}
}
And in your class where you need the location, just add these line:
var latitude: CLLocationDegrees = descLocation.latitude
var longtitude: CLLocationDegrees = descLocation.longitude
var location: CLLocationCoordinate2D = CLLocationCoordinate2D(latitude: latitude, longitude: longtitude)
So you can add annotation to your map using this code:
#IBOutlet var map: MKMapView!
var annotation = MKPointAnnotation()
annotation.title = "Test"
annotation.coordinate = location
map.addAnnotation(annotation)

Related

Cannot save the longitute and latitude from CLGeocoder()

I want to retrieve the longitute and latitude using an address as a string. I found this very useful post here: Convert address to coordinates swift
But when I want to save the results in a double field and return it I can't. What I have done is
func getLatitude(address:String) -> Double{
var lati = 0.0
var geocoder = CLGeocoder()
geocoder.geocodeAddressString("your address") {
placemarks, error in
let placemark = placemarks?.first
if let lat = placemark?.location?.coordinate.latitude{
lati = lat
}
}
}
return lati
}
Inside the geocoder.geocodeAddressString block the value is populated but when I try to return it always gives me 0.0 and I have tried everything. Any ideas please?
If it try to print the value inside the inner block of code it gets printed but I can never return it.
Thank you in advance for the answers.
CLLocationCoordinate2D is struct of latitude and longitude both defined as CLLocationDegrees which itself is a typealias of Double.
var latitude: Double?
var longitude: Double?
func getLocation(address: String) {
let geocoder = CLGeocoder()
geocoder.geocodeAddressString(address) { placemarks, error in
guard let placemark = placemarks?.first else { return }
let coordinate = placemark.location?.coordinate
latitude = coordinate?.latitude
longitude = coordinate?.longitude
}
}

Access to the coordinates from an address swift

Hi how can I access to the longitude and latitude parameters outside of this block ?
let geocoder = CLGeocoder()
geocoder.geocodeAddressString(address) { placemarks, error in
let placemark = placemarks?.first
let lat = placemark?.location?.coordinate.latitude
let lon = placemark?.location?.coordinate.longitude
print("Lat: \(lat), Lon: \(lon)")
}
I want to save this two params as Float or String in firebase. Thanks
You can create a function like this:
func getLatAndLong(address : String, competion : #escaping (CLLocationCoordinate2D?) -> ()) {
let geocoder = CLGeocoder()
geocoder.geocodeAddressString(address) { placemarks, error in
let placemark = placemarks?.first
let lat = placemark?.location?.coordinate.latitude
let lon = placemark?.location?.coordinate.longitude
print("Lat: \(lat), Lon: \(lon)")
competion(placemark?.location?.coordinate)
}
}
and then call it as :
var location : CLLocationCoordinate2D?
getLatAndLong(address: "pass your address here") { (coordinates) in
self.location = coordinates
}
Now your location variable holds the value.
you can use it to get latitide and longitude
let latitide = location?.latitude
let longitude = location?.longitude
Option 2
You can declare a variable in class and update its you value once you get the coordinates. I would suggest using the above approach as geocoder runs asynchronously. Its better to use a completion handler to know when the geoCoder has finished executing the task and has got the location.
var latitude = 0.0 //
var longitude = 0.0
let geocoder = CLGeocoder()
geocoder.geocodeAddressString("address") { placemarks, error in
let placemark = placemarks?.first
self.latitude = placemark?.location?.coordinate.latitude ?? 0.0
self.longitude = placemark?.location?.coordinate.longitude ?? 0.0
}

how to save the co-ordinate as PFGeopoint with ios parse.com

I want to add the longitude and latitude from the user using textfield and that value to pass in PFGeoPoint.But Textfield value is in string that not consideras PFGeoPoint. My code is:
#IBOutlet weak var latitue_filed: UITextField!
#IBOutlet weak var longitudead: UITextField!
let lati : = (latitue_filed.text as? PFGeoPoint)!
let lon : = (longitudead.text as? PFGeoPoint)!
let myGeoPoint = PFGeoPoint(latitude: lat, longitude: lon)
posts["location"] = myGeoPoint
posts.saveInBackgroundWithBlock {
(success: Bool, error: NSError?) -> Void in
if (success) {
// The object has been saved.
} else {
// There was a problem, check error.description
}
}
posts.saveInBackground()`
Here latitue_filed and longitudead is textfield. How can i pass textfield value in PfGeopint.
According to documentation, PFGeoPoint is actually a PFObject which uses doubles latitude and longitude (Which are degrees) and embeds them together. You are currently casting string values from textfield to individual PFGeoPoints. Cast the string values to double and use the method described in the documentation to create a PFGeoPoint.
let lati = Double(latitue_filed.text)
let lon = Double(longitudead.text)
let myGeoPoint = PFGeoPoint(latitude: lat, longitude: lon)
posts["location"] = myGeoPoint
posts.saveInBackgroundWithBlock {
(success: Bool, error: NSError?) -> Void in
if (success) {
// The object has been saved.
} else {
// There was a problem, check error.description
}
}

Converting CLLocationCoordinate2D to a String that can be stored

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)
}

Map with Photos using Parse

I'm trying to do exactly this using Parse and Swift.
import UIKit
import MapKit
import CoreLocation
class MapViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {
var latitude:Double = 0.0
var longitude:Double = 0.0
#IBOutlet var map: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.setNavigationBarHidden(true , animated: true)
self.map.showsUserLocation = true
self.map.delegate = self
PFGeoPoint.geoPointForCurrentLocationInBackground { (geopoint:PFGeoPoint?, error:NSError?) -> Void in
var query = PFQuery(className: "Locations")
query.whereKey("geopoint", nearGeoPoint: geopoint!)
query.findObjectsInBackgroundWithBlock { (objects, error) -> Void in
if let myObjects = objects {
for object in myObjects {
var thePoint: PFGeoPoint = object["geopoint"] as! PFGeoPoint
self.latitude = thePoint.latitude
self.longitude = thePoint.longitude
NSLog(" Hej %f, %f", self.latitude, self.longitude)
var annotationCoordinate: CLLocationCoordinate2D = CLLocationCoordinate2DMake(self.latitude, self.longitude)
var annotation = MKPointAnnotation()
annotation.coordinate = annotationCoordinate
annotation.title = object["discovery"] as! String
annotation.subtitle = object["location"] as! String
self.map.addAnnotation(annotation)
}
}
}
}
}
Big picture though, I'm trying to create a way to access pictures stored on Parse (and their locations) and display them on a map if they meet my query. I greatly appreciate any help!
if you are getting the conversion error in
var thePoint: PFGeoPoint = object["geopoint"]
change it to
var thePoint: PFGeoPoint = object["geopoint"] as! PFGeoPoint
Regarding converting Double to Int, it appears to be as you found but I don't know the rationale behind the decision by the designers of swift. I would like to understand why you need the conversion since there may be an alternate implementation

Resources