In this blog, I will be using two frameworks for locations, CoreLocation and MapKit.
- CoreLocation: used to manage operations related to coordinates and address
- MapKit: used to manage any operations related to drawing a map on the screen
Forward Geocoding
- translate a human-readable address -> coordinates (latitude + longitude)
- submit the address to Apple's geocoding server as a background task
import UIKit
// MARK: 1. import the CoreLocation Library
// - has methods and properties that allow you to manage addresses and coordinates
import CoreLocation
class ForwardGeoVC: UIViewController {
// MARK: Outlets
@IBOutlet weak var streetTF: UITextField!
@IBOutlet weak var cityTF: UITextField!
@IBOutlet weak var countryTF: UITextField!
@IBOutlet weak var coordinatesLabel: UILabel!
// MARK: 2. Geocoder object
let geocoder = CLGeocoder()
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func fetchCoordinates(_ sender: Any) {
guard let street = streetTF.text,
let city = cityTF.text,
let country = countryTF.text
else {return}
print("\(country), \(city), \(street)")
getLocation(address: "\(country), \(city), \(street)")
}
// helper function
func getLocation(address: String) {
// MARK: 3. Forward geocoding request
// - Taking a human readable addresss and converting it to a coordinate
geocoder.geocodeAddressString(address) { results, error in
print("Sent request to geocoding service, waiting for response")
// unsuccessful
if (error != nil) {
print("Error occured during geocoding request:")
print(error ?? "")
self.coordinatesLabel.text = "An error occured, try again later."
return
}
// success
if(results != nil) {
if(results?.count == 0) {
// not able to find a coordinate
print("No coordinates found for this address")
self.coordinatesLabel.text = "No coordinates found for this address"
} else {
// able to find a coordinate
print("Coordinate found")
let placemark: CLPlacemark = (results?.first)!
print(placemark)
// extract the relevant data (lat, long)
if let lat = placemark.location?.coordinate.latitude,
let long = placemark.location?.coordinate.longitude {
print("Coordinate: \(lat), \(long)")
self.coordinatesLabel.text = "\(lat), \(long)"
} else {
print("Could not extract coordinates")
self.coordinatesLabel.text = "Could not extract coordinates"
}
}
}
}
}
}
Reverse Geocoding
- translate a set of coordinates (latitude + longitude) -> human readable address
import UIKit
// MARK: 1. import CoreLocation
import CoreLocation
class ReverseGeoVC: UIViewController {
// MARK: Outlets
@IBOutlet weak var latitudeTF: UITextField!
@IBOutlet weak var longitudeTF: UITextField!
@IBOutlet weak var addressLabel: UILabel!
// MARK: 2. Geocoder object
let geocoder = CLGeocoder()
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func fetchAddress(_ sender: Any) {
guard let lat = latitudeTF.text,
let long = longitudeTF.text
else {return}
print("Got coordinates: (\(lat), \(long))")
getAddress(latitude:lat, longitude: long)
}
// helper function
func getAddress(latitude:String, longitude:String) {
// MARK: 3. Reverse geocoding request
// - Taking a coordinate and converting it to a human readable addresss
guard let latDouble = Double(latitude),
let longDouble = Double(longitude)
else {return}
let location = CLLocation(latitude: latDouble, longitude: longDouble)
geocoder.reverseGeocodeLocation(location) { results, error in
print("Sent request to geocoding service, waiting for response")
if let err = error {
print("Error occured during geocoding request: \(err)")
self.addressLabel.text = "An error occured, try again later."
}
if let res = results {
if (res.count == 0) {
// not able to find a coordinate
print("No addresses found for this coordinate")
} else {
// able to find a coordinate
print("Address found")
let placemark:CLPlacemark = res.first!
print("Placemark: \(placemark)")
//compose an actual address
let name = placemark.name ?? ""
let street = "\(placemark.subThoroughfare ?? "") \(placemark.thoroughfare ?? "")"
let city = placemark.locality ?? ""
let province = placemark.administrativeArea ?? ""
let country = placemark.country ?? ""
let address = "\(name) \(street), \(city), \(province), \(country)"
print("Final address: \(address)")
self.addressLabel.text = address
}
}
}
}
}
Main Map View Controller
import UIKit
// MARK: 1. import MapKit
import MapKit
class MapVC: UIViewController {
// MARK: 2. Create an outlet for your map
@IBOutlet weak var mapView: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
// MARK: 3. Code to configure the map
// See: https://guides.codepath.com/ios/Maps#set-up-initial-properties
// span = describes the zoom level of your map
// smaller numbers = more zoomed in
// larger numbers = more zoomed out
// 0.01 = street level zoom
let zoomLevel = MKCoordinateSpan(latitudeDelta: 0.05, longitudeDelta: 0.05)
// region = visible area of the map --> center of your map
let centerOfMap = CLLocationCoordinate2D(latitude: 43.7957894, longitude: -79.3489909)
let visibleRegion = MKCoordinateRegion(center: centerOfMap, span: zoomLevel)
// setup the map to show this region
mapView.setRegion(visibleRegion, animated: true)
// MARK: 4. Add a pin on the map
// See: https://guides.codepath.com/ios/Maps#mkpointannotation
let pin = MKPointAnnotation()
pin.coordinate = centerOfMap
pin.title = "Seneca College - Newnham Campus"
mapView.addAnnotation(pin)
}
}
Top comments (0)