How does one convert a zip, or in my case a postal code(UK) to lat long coordinates?
I read upon using google geocoding api but read that is has a fair amount of restrictions such as using google maps in the application and limit to requests.
I also found this but I'm not to sure how to go about implementing it
You would want to use the GeocodeAddressDictionary which accepts a dictionary of specific address types.
In your case, you would do the following.
let geocoder = CLGeocoder()
let dic = [NSTextCheckingZIPKey: yourZipCode]
geocoder.geocodeAddressDictionary(dic) { (placemark, error) in
if((error) != nil){
print(error!)
}
if let placemark = placemark?.first {
let lat = placemark.location!.coordinate.latitude
let long = placemark.location!.coordinate.longitude
}
}
With this code you can do it providing the address (Will be more accurate because a zip code is not a concrete coordinate but an address it is).
Remember to import CoreLocation at the top of the class.
let address = "1 Infinite Loop, CA, USA"
let geocoder = CLGeocoder()
geocoder.geocodeAddressString(address, completionHandler: {(placemarks, error) -> Void in
if((error) != nil){
print("Error", error)
}
if let placemark = placemarks?.first {
let coordinates:CLLocationCoordinate2D = placemark.location!.coordinate
}
})
Related
I am trying convert to addresses into latlongs to place them on googleMap but, when I pass the address String to geoCoder.geoAddressString(fullAddress) and running application, completionHandler is not executing, I tried with breakpoint at geoCoder.geocodeAddressString(fullAddress) { (placemarks, error) and when I click on stepover it is coming out if the completionHandler..
Now, I have no idea why this is happening... Does anyone know? please Help..
see My code Here:
func loadMarkers() {
for i in 0..<self.professioanlDetailsAH.count {
let fullAddress = "\(self.professioanlDetailsAH[i]["searchAddress"]!)"
if !fullAddress.isEmpty {
var geoCoder = CLGeocoder()
geoCoder.geocodeAddressString(fullAddress) { (placemarks, error) in
guard
let placemarks = placemarks,
let addressLocation = placemarks.first?.location
else {
// handle no location found
return
}
let latitude = addressLocation.coordinate.latitude
let longitude = addressLocation.coordinate.longitude
}
}
}
}
Edit:
func loadMarkers() {
for i in 0..<self.professioanlDetailsAH.count {
print(self.professioanlDetailsAH[i]["firstName"]!)
let fullAddress = "\(self.professioanlDetailsAH[i]["searchAddress"]!)"
print(fullAddress)
if !fullAddress.isEmpty {
geoCoder.geocodeAddressString(fullAddress) {(placemarks, error) in
if error != nil {
print(error!)
}
else{
guard
let placemarks = placemarks,
let addressLocation = placemarks.first?.location
else {return}
let latitude = addressLocation.coordinate.latitude
let longitude = addressLocation.coordinate.longitude
print("lat:\(latitude), long:\(longitude)")
}
}
}
}
I am having a bit of trouble understanding Apple's MapKit in Swift 3.
I found an example here: How to open maps App programmatically with coordinates in swift?
public func openMapForPlace(lat:Double = 0, long:Double = 0, placeName:String = "") {
let latitude: CLLocationDegrees = lat
let longitude: CLLocationDegrees = long
let regionDistance:CLLocationDistance = 100
let coordinates = CLLocationCoordinate2DMake(latitude, longitude)
let regionSpan = MKCoordinateRegionMakeWithDistance(coordinates, regionDistance, regionDistance)
let options = [
MKLaunchOptionsMapCenterKey: NSValue(mkCoordinate: regionSpan.center),
MKLaunchOptionsMapSpanKey: NSValue(mkCoordinateSpan: regionSpan.span)
]
let placemark = MKPlacemark(coordinate: coordinates, addressDictionary: nil)
let mapItem = MKMapItem(placemark: placemark)
mapItem.name = placeName
mapItem.openInMaps(launchOptions: options)
}
This works absolutely swimmingly, except that I need to use an address instead of coordinates in this case.
I have found methods for doing this using google maps, but I cant seem to find a specific answer for Apple Maps, if it exists, I've completed glazed over it.
If anyone can help me to understand what the correct approach is, that would be amazing. I'm using:
Xcode 8.3.1
Swift 3.1
macOS
Targeting iOS 10+
You need to use the Geocoding service to convert an address to the corresponding geolocation.
For instance, add this function to your toolkit:
func coordinates(forAddress address: String, completion: #escaping (CLLocationCoordinate2D?) -> Void) {
let geocoder = CLGeocoder()
geocoder.geocodeAddressString(address) {
(placemarks, error) in
guard error == nil else {
print("Geocoding error: \(error!)")
completion(nil)
return
}
completion(placemarks.first?.location?.coordinate)
}
}
and then use it like this:
coordinates(forAddress: "YOUR ADDRESS") {
(location) in
guard let location = location else {
// Handle error here.
return
}
openMapForPlace(lat: location.latitude, long: location.longitude)
}
You need to use geoCode to get the coordinates from the address... This should work:
let geocoder = CLGeocoder()
geocoder.geocodeAddressString("ADDRESS_STRING") { (placemarks, error) in
if error != nil {
//Deal with error here
} else if let placemarks = placemarks {
if let coordinate = placemarks.first?.location?.coordinate {
//Here's your coordinate
}
}
}
How can I convert a String address to CLLocation coordinates with Swift?
I have no code yet; I looked for a solution but couldn't find any.
Use CLGeocoder to reverse geocode the address into latitude/longitude coordinates:
let address = "1 Infinite Loop, Cupertino, CA 95014"
let geoCoder = CLGeocoder()
geoCoder.geocodeAddressString(address) { (placemarks, error) in
guard
let placemarks = placemarks,
let location = placemarks.first?.location
else {
// handle no location found
return
}
// Use your location
}
You will also need to add and import CoreLocation framework.
You can use CLGeocoder, you can convert address(string) to coordinate and you vice versa, try this:
import CoreLocation
var geocoder = CLGeocoder()
geocoder.geocodeAddressString("your 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)")
}
Here's what I came up with to return a CLLocationCoordinat2D object:
func getLocation(from address: String, completion: #escaping (_ location: CLLocationCoordinate2D?)-> Void) {
let geocoder = CLGeocoder()
geocoder.geocodeAddressString(address) { (placemarks, error) in
guard let placemarks = placemarks,
let location = placemarks.first?.location?.coordinate else {
completion(nil)
return
}
completion(location)
}
}
So let's say I've got this address:
let address = "Springfield, Illinois"
Usage
getLocation(from: address) { location in
print("Location is", location.debugDescription)
// Location is Optional(__C.CLLocationCoordinate2D(latitude: 39.799372, longitude: -89.644458))
}
Swift 5 and Swift 5.1
import CoreLocation
var geocoder = CLGeocoder()
geocoder.geocodeAddressString("your 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)")
}
This works
let geocoder = CLGeocoder()
let address = "8787 Snouffer School Rd, Montgomery Village, MD 20879"
geocoder.geocodeAddressString(address, completionHandler: {(placemarks, error) -> Void in
if((error) != nil){
print("Error", error ?? "")
}
if let placemark = placemarks?.first {
let coordinates:CLLocationCoordinate2D = placemark.location!.coordinate
print("Lat: \(coordinates.latitude) -- Long: \(coordinates.longitude)")
}
})
The CLLocationManager object reports locations as a latitude/longitude pair. While these values uniquely represent any location on the planet, they are not values that users immediately associate with the location. Users are more familiar with names that describe a location, such as street names or city names. The CLGeocoder class lets you convert between geographic coordinates and the user-friendly names associated with that location. You can convert from either a latitude/longitude pair to a user friendly place name, or the other way around.
func getCoordinate( addressString : String,
completionHandler: #escaping(CLLocationCoordinate2D, NSError?) -> Void ) {
let geocoder = CLGeocoder()
geocoder.geocodeAddressString(addressString) { (placemarks, error) in
if error == nil {
if let placemark = placemarks?[0] {
let location = placemark.location!
completionHandler(location.coordinate, nil)
return
}
}
completionHandler(kCLLocationCoordinate2DInvalid, error as NSError?)
}
}
I am trying to recover all the animal objects based on certain parameters. First I need to retrieve their location from parse as well as the name, but since I am importing more than one and using geocoder, I am using strings, and not an array. So instead of appending the imported information into an array, I am mutating a variable. What I though would happen is the query would go through the first object then run the retrieveLocation method, then proceed to the next object imported from parse, but instead it imports everything then runs the method, so in the end I only get 1 object instead of how many are supposed to be imported.
let query = PFQuery(className: "Animals")
query.findObjectsInBackgroundWithBlock { (objects: [PFObject]?, error: NSError?) in
if(error == nil){
for object in objects!{
if let addressobj = object["Add"] as? NSDictionary{
if let address = addressobj["address"] as? String{
self.addr = address
print("sdfadsf \(self.addr)")
}
}
if let name = object["Name"] as? String{
self.impname = name
print("rturrty \(self.impname)")
self.retrieveLocation()
}
}
}
}
func retrieveLocation(){
let geocoder = CLGeocoder()
geocoder.geocodeAddressString(addr, completionHandler: {(placemarks, error) -> Void in
if((error) != nil){
print("Error", error)
}
if let placemark = placemarks?.first {
let coordinates = PFGeoPoint(location: placemark.location)
if(whatever is true){
append the name and address into an array. This is the part where I just get repeats of the LATEST imported object.
}
}
})
}
This should work if you use a local variable and pass this local variable to an implementation of retrieveLocation that takes a string as a parameter retrieveLocation(address: String)
let query = PFQuery(className: "Animals")
query.findObjectsInBackgroundWithBlock { (objects: [PFObject]?, error: NSError?) in
if(error == nil){
for object in objects!{
if let addressobj = object["Add"] as? NSDictionary{
if let address = addressobj["address"] as? String{
let newAddress = address
print("sdfadsf \(self.addr)")
}
}
if let name = object["Name"] as? String{
self.impname = name
print("rturrty \(self.impname)")
self.retrieveLocation(newAdress)
}
}
}
}
func retrieveLocation(address: String){
let geocoder = CLGeocoder()
geocoder.geocodeAddressString(address, completionHandler: {(placemarks, error) -> Void in
if((error) != nil){
print("Error", error)
}
if let placemark = placemarks?.first {
let coordinates = PFGeoPoint(location: placemark.location)
if(whatever is true){
append the name and address into an array. This is the part where I just get repeats of the LATEST imported object.
}
}
})
}
Problem seems to be that by the time self.addr is being used in the geocodeAddresString method, the for-loop has finished and thus overwritten all the previous values that were at one point individually held by self.addr. By using a local variable, it will be sure to use a unique value to geocodeAddressString each time it is executed
Since ABCreateStringWithAddressDictionary is deprecated in iOS9, what other option is it to get address string from CLGeocoder?
This is my solution:
let geocoder = CLGeocoder()
geocoder.reverseGeocodeLocation(location, completionHandler: { (placemarks, error) in
if error != nil {
print("Error: \(error?.localizedDescription)")
}
if let myMarks = placemarks {
if let placemark = myMarks.last {
if let addressLine = (placemark.addressDictionary?["FormattedAddressLines"] as? [String]) {
self.addressLabel.text = addressLine.joined(separator: ", ")
}
}
}
})
El Key "FormattedAddressLines" return an array with this order: Name, Street, City, State, ZIP, Country. if you print addressLine, you'll see something like this: "Apple Inc., 1 Infinite Loop, Cupertino, CA 95014, United States".