Reverse geocoding in Swift 4












9















I'm attempting to write a simple method that's fed CLLocationDegrees and returns a CLPlacemark. Looking at Apple's documentation, it seems like a simple task.



Below is what I've dumped into a playground:



import CoreLocation
// this is necessary for async code in a playground
import PlaygroundSupport

// this is necessary for async code in a playground
PlaygroundPage.current.needsIndefiniteExecution = true

func geocode(latitude: CLLocationDegrees, longitude: CLLocationDegrees) -> CLPlacemark? {
let location = CLLocation(latitude: latitude, longitude: longitude)
let geocoder = CLGeocoder()

var placemark: CLPlacemark?

geocoder.reverseGeocodeLocation(location) { (placemarks, error) in
if error != nil {
print("something went horribly wrong")
}

if let placemarks = placemarks {
placemark = placemarks.first
}
}

return placemark
}

let myPlacemark = geocode(latitude: 37.3318, longitude: 122.0312)


As it stands, my method is returning nil. I'm not sure where my error lies, but I rest assured it's something starlingly stupid on my part. Thank you for reading.










share|improve this question




















  • 3





    geocoder.reverseGeocodeLocation is async you would need a completion handler

    – Leo Dabus
    Oct 22 '17 at 0:48











  • Thank you. I'll see if I can figure it out.

    – Adrian
    Oct 22 '17 at 0:53











  • I'm trying to pass coordinates that are stored as Doubles in Core Data.

    – Adrian
    Oct 22 '17 at 1:18
















9















I'm attempting to write a simple method that's fed CLLocationDegrees and returns a CLPlacemark. Looking at Apple's documentation, it seems like a simple task.



Below is what I've dumped into a playground:



import CoreLocation
// this is necessary for async code in a playground
import PlaygroundSupport

// this is necessary for async code in a playground
PlaygroundPage.current.needsIndefiniteExecution = true

func geocode(latitude: CLLocationDegrees, longitude: CLLocationDegrees) -> CLPlacemark? {
let location = CLLocation(latitude: latitude, longitude: longitude)
let geocoder = CLGeocoder()

var placemark: CLPlacemark?

geocoder.reverseGeocodeLocation(location) { (placemarks, error) in
if error != nil {
print("something went horribly wrong")
}

if let placemarks = placemarks {
placemark = placemarks.first
}
}

return placemark
}

let myPlacemark = geocode(latitude: 37.3318, longitude: 122.0312)


As it stands, my method is returning nil. I'm not sure where my error lies, but I rest assured it's something starlingly stupid on my part. Thank you for reading.










share|improve this question




















  • 3





    geocoder.reverseGeocodeLocation is async you would need a completion handler

    – Leo Dabus
    Oct 22 '17 at 0:48











  • Thank you. I'll see if I can figure it out.

    – Adrian
    Oct 22 '17 at 0:53











  • I'm trying to pass coordinates that are stored as Doubles in Core Data.

    – Adrian
    Oct 22 '17 at 1:18














9












9








9


6






I'm attempting to write a simple method that's fed CLLocationDegrees and returns a CLPlacemark. Looking at Apple's documentation, it seems like a simple task.



Below is what I've dumped into a playground:



import CoreLocation
// this is necessary for async code in a playground
import PlaygroundSupport

// this is necessary for async code in a playground
PlaygroundPage.current.needsIndefiniteExecution = true

func geocode(latitude: CLLocationDegrees, longitude: CLLocationDegrees) -> CLPlacemark? {
let location = CLLocation(latitude: latitude, longitude: longitude)
let geocoder = CLGeocoder()

var placemark: CLPlacemark?

geocoder.reverseGeocodeLocation(location) { (placemarks, error) in
if error != nil {
print("something went horribly wrong")
}

if let placemarks = placemarks {
placemark = placemarks.first
}
}

return placemark
}

let myPlacemark = geocode(latitude: 37.3318, longitude: 122.0312)


As it stands, my method is returning nil. I'm not sure where my error lies, but I rest assured it's something starlingly stupid on my part. Thank you for reading.










share|improve this question
















I'm attempting to write a simple method that's fed CLLocationDegrees and returns a CLPlacemark. Looking at Apple's documentation, it seems like a simple task.



Below is what I've dumped into a playground:



import CoreLocation
// this is necessary for async code in a playground
import PlaygroundSupport

// this is necessary for async code in a playground
PlaygroundPage.current.needsIndefiniteExecution = true

func geocode(latitude: CLLocationDegrees, longitude: CLLocationDegrees) -> CLPlacemark? {
let location = CLLocation(latitude: latitude, longitude: longitude)
let geocoder = CLGeocoder()

var placemark: CLPlacemark?

geocoder.reverseGeocodeLocation(location) { (placemarks, error) in
if error != nil {
print("something went horribly wrong")
}

if let placemarks = placemarks {
placemark = placemarks.first
}
}

return placemark
}

let myPlacemark = geocode(latitude: 37.3318, longitude: 122.0312)


As it stands, my method is returning nil. I'm not sure where my error lies, but I rest assured it's something starlingly stupid on my part. Thank you for reading.







ios swift cllocationmanager






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Oct 22 '17 at 1:33







Adrian

















asked Oct 22 '17 at 0:30









AdrianAdrian

8,507860129




8,507860129








  • 3





    geocoder.reverseGeocodeLocation is async you would need a completion handler

    – Leo Dabus
    Oct 22 '17 at 0:48











  • Thank you. I'll see if I can figure it out.

    – Adrian
    Oct 22 '17 at 0:53











  • I'm trying to pass coordinates that are stored as Doubles in Core Data.

    – Adrian
    Oct 22 '17 at 1:18














  • 3





    geocoder.reverseGeocodeLocation is async you would need a completion handler

    – Leo Dabus
    Oct 22 '17 at 0:48











  • Thank you. I'll see if I can figure it out.

    – Adrian
    Oct 22 '17 at 0:53











  • I'm trying to pass coordinates that are stored as Doubles in Core Data.

    – Adrian
    Oct 22 '17 at 1:18








3




3





geocoder.reverseGeocodeLocation is async you would need a completion handler

– Leo Dabus
Oct 22 '17 at 0:48





geocoder.reverseGeocodeLocation is async you would need a completion handler

– Leo Dabus
Oct 22 '17 at 0:48













Thank you. I'll see if I can figure it out.

– Adrian
Oct 22 '17 at 0:53





Thank you. I'll see if I can figure it out.

– Adrian
Oct 22 '17 at 0:53













I'm trying to pass coordinates that are stored as Doubles in Core Data.

– Adrian
Oct 22 '17 at 1:18





I'm trying to pass coordinates that are stored as Doubles in Core Data.

– Adrian
Oct 22 '17 at 1:18












2 Answers
2






active

oldest

votes


















21














import UIKit
import CoreLocation
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true




func geocode(latitude: Double, longitude: Double, completion: @escaping (_ placemark: [CLPlacemark]?, _ error: Error?) -> Void)  {
CLGeocoder().reverseGeocodeLocation(CLLocation(latitude: latitude, longitude: longitude)) { placemark, error in
guard let placemark = placemark, error == nil else {
completion(nil, error)
return
}
completion(placemark, nil)
}
}


or simply:



func geocode(latitude: Double, longitude: Double, completion: @escaping (_ placemark: [CLPlacemark]?, _ error: Error?) -> Void)  {
CLGeocoder().reverseGeocodeLocation(CLLocation(latitude: latitude, longitude: longitude), completionHandler: completion)
}


or extending CLLocation:



extension CLLocation {
func geocode(completion: @escaping (_ placemark: [CLPlacemark]?, _ error: Error?) -> Void) {
CLGeocoder().reverseGeocodeLocation(self, completionHandler: completion)
}
}




To format your place mark as a mailing address you can use Contacts framework CNPostalAddressFormatter:



import Contacts

extension Formatter {
static let mailingAddress: CNPostalAddressFormatter = {
let formatter = CNPostalAddressFormatter()
formatter.style = .mailingAddress
return formatter
}()
}

extension CLPlacemark {
var mailingAddress: String? {
return postalAddress?.mailingAddress
}
}

extension CNPostalAddress {
var mailingAddress: String {
return Formatter.mailingAddress.string(from: self)
}
}





placemark



Contains an array of CLPlacemark objects. For most geocoding requests,
this array should contain only one entry. However, forward-geocoding
requests may return multiple placemark objects in situations where the
specified address could not be resolved to a single location. If the
request was canceled or there was an error in obtaining the placemark
information, this parameter is nil.




For more information about the CLPlacemark properties you can check this CLPlacemark





Usage:



let location = CLLocation(latitude: -22.963451, longitude: -43.198242)
location.geocode { placemark, error in
if let error = error as? CLError {
print("CLError:", error)
return
} else if let placemark = placemark?.first {
// you should always update your UI in the main thread
DispatchQueue.main.async {
// update UI here
print("name:", placemark.name ?? "unknown")

print("address1:", placemark.thoroughfare ?? "unknown")
print("address2:", placemark.subThoroughfare ?? "unknown")
print("neighborhood:", placemark.subLocality ?? "unknown")
print("city:", placemark.locality ?? "unknown")

print("state:", placemark.administrativeArea ?? "unknown")
print("subAdministrativeArea:", placemark.subAdministrativeArea ?? "unknown")
print("zip code:", placemark.postalCode ?? "unknown")
print("country:", placemark.country ?? "unknown", terminator: "nn")

print("isoCountryCode:", placemark.isoCountryCode ?? "unknown")
print("region identifier:", placemark.region?.identifier ?? "unknown")

print("timezone:", placemark.timeZone ?? "unknown", terminator:"nn")

// Mailind Address
print(placemark.mailingAddress ?? "unknown")
}
}
}




This will print



name: Morro da Saudade
address1: Rua Casuarina
address2: 597
neighborhood: Lagoa
city: Rio de Janeiro
state: RJ
subAdministrativeArea: unknown
zip code: 22011-040
country: Brazil

isoCountryCode: BR
region identifier: <-22.96345100,-43.19824200> radius 141.83
timezone: America/Sao_Paulo (current)



Rua Casuarina, 597



Lagoa



Rio de Janeiro RJ



22011-040



Brazil







share|improve this answer


























  • Thank you! This gets the job done. I don't think I'm going to be able to declare a let constant like this, given it's async code. I'll refactor this let myPlacemark = geocode(latitude: 37.3318, longitude: 122.0312) with something else.

    – Adrian
    Oct 22 '17 at 1:25











  • You need to use it inside the closure

    – Leo Dabus
    Oct 22 '17 at 1:26











  • Perfect. Thank you!

    – Adrian
    Oct 22 '17 at 1:29











  • HI, How to get the complete state name?, not in ISO code format.

    – Ramakrishna
    Jan 6 '18 at 11:22



















0














There are so many questions dealing with 'reverseGeocodeLocation' on Stack Overflow, I've seen so many of them. I'm using Swift 4.2 and I thought my 'reverseGeocodeLocation' requests might be timing out. Well, this is NOT the case, when starting to move with an iPhone the 'didUpdateLocations' cycles need to mature. It can take two or more cycles before 'reverseGeocodeLocation' returns placemarks.



I wrote a simple app that uses 'reverseGeocodeLocation' until 'placemarks' are returned after repeated 'didUpdateLocations' cycles. This is my own home grown 'SampleCode'. I learned a lot from using the app, it might help others understand how reverse geocode requests work in the real world.



Please give your comments on possible improvements. This code is freely given and freely taken.



import Foundation
import UIKit
import CoreLocation

class ViewController: UIViewController, CLLocationManagerDelegate {
@IBAction func RefreshLocationButton(_ sender: Any) {
self.requestingPlacemark = true
self.placemarkData = nil
//^Make another Placemark Request
self.requestCounter = 0
self.RequestCounterLabel.text = ""
self.LocationLabel.text = ""
self.PlacemarkLabel.text = ""}
@IBOutlet weak var LocationCounterLabel: UILabel!
@IBOutlet weak var RequestCounterLabel: UILabel!
@IBOutlet weak var LocationLabel: UILabel!
@IBOutlet weak var PlacemarkLabel: UILabel!
let locationManager = CLLocationManager()
var placemarkData: CLPlacemark!
var placemarkString: String!
var printPlacemarkData: Bool!
var didUpdateLocationsCounter: Int = 0
var requestCounter: Int = 0
var requestingPlacemark: Bool = true

override func viewDidLoad() {
super.viewDidLoad()
if CLLocationManager.locationServicesEnabled() {
locationManager.requestAlwaysAuthorization()
locationManager.delegate = self
//locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation
locationManager.startUpdatingLocation()
self.RequestCounterLabel.text = ""
self.LocationLabel.text = ""
self.PlacemarkLabel.text = ""}}
func printPlacemarks() {
if printPlacemarkData {
self.placemarkString = "Placemark Data:"
self.placemarkString = buildPlacemarkString(item: 1)
self.placemarkString = buildPlacemarkString(item: 2)
self.placemarkString = buildPlacemarkString(item: 3)
self.placemarkString = buildPlacemarkString(item: 4)
self.placemarkString = buildPlacemarkString(item: 5)
self.placemarkString = buildPlacemarkString(item: 6)
self.placemarkString = buildPlacemarkString(item: 7)
self.placemarkString = buildPlacemarkString(item: 8)
self.placemarkString = buildPlacemarkString(item: 9)
self.placemarkString = buildPlacemarkString(item: 10)
self.PlacemarkLabel.text = self.placemarkString
self.printPlacemarkData = false}}
func buildPlacemarkString(item: Int) -> String {
var elementText: String!
var newString: String!
switch item {
case 1: elementText = "name: " + self.placemarkData.name!
case 2: elementText = "subThoroughfare: " + self.placemarkData.subThoroughfare!
case 3: elementText = "thoroughfare: " + self.placemarkData.thoroughfare!
case 4: elementText = "postalCode: " + self.placemarkData.postalCode!
case 5: elementText = "subLocality: " + self.placemarkData.subLocality!
case 6: elementText = "locality: " + self.placemarkData.locality!
case 7: elementText = "subAdministrativeArea: " + self.placemarkData.subAdministrativeArea!
case 8: elementText = "administrativeArea: " + self.placemarkData.administrativeArea!
case 9: elementText = "country: " + self.placemarkData.country!
case 10: elementText = "isoCountryCode: " + self.placemarkData.isoCountryCode!
default: print("Error: incorrect item number!")}
newString = self.placemarkString + "n" + elementText
return newString
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
//location prints one time and 'didUpdateLocations' is stopped:
self.didUpdateLocationsCounter = self.didUpdateLocationsCounter + 1
let labelString = String(describing: self.didUpdateLocationsCounter)
self.LocationCounterLabel.text = "Location Update Counter: " + labelString
if self.placemarkData == nil {
//location variable:
self.requestCounter = self.requestCounter + 1
let textString = String(describing: self.requestCounter)
self.RequestCounterLabel.text = "Request Counter: " + textString
if locations.count == 0 {
self.LocationLabel.text = "Locations: There was NONE"}
else {
if locations.count > 0 {
let coordinate2D: CLLocation = locations.first!
let location = CLLocation(latitude: coordinate2D.coordinate.latitude, longitude: coordinate2D.coordinate.longitude)
let printString = String(describing: location)
self.LocationLabel.text = "Location: " + printString
let geocoder: CLGeocoder = CLGeocoder()
geocoder.reverseGeocodeLocation(location, completionHandler: {(placemarks, error) -> Void in
if error != nil {
let errorString = String(describing: error?.localizedDescription)
print("reverse geodcode fail: (errorString)")
self.LocationCounterLabel.text = ""
self.RequestCounterLabel.text = ""
self.LocationLabel.text = "Reverse Geodcode fail: (errorString)"
self.PlacemarkLabel.text = ""
self.requestingPlacemark = false
return}
else {
let pm = placemarks! as [CLPlacemark]
//There is ALWAYS 'placemarks' Data
if pm.count > 0 {
self.placemarkData = placemarks![0]
self.printPlacemarkData = true
self.printPlacemarks()
self.requestingPlacemark = false}}})}
else {
if self.requestingPlacemark {
self.LocationLabel.text = "Problem: There is no 'location.first'"}}}}}}


And then the Storyboard UI:



Storyboard Image



View Controller Image



<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14460.20"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="tne-QT-ifu">
<objects>
<viewController id="BYZ-38-t0r" customClass="ViewController" customModule="MyThoroughfare" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Location Counter" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ZIg-u9-TMR">
<rect key="frame" x="16" y="20" width="343" height="20.5"/>
<color key="backgroundColor" red="0.80000001190000003" green="0.80000001190000003" blue="0.80000001190000003" alpha="1" colorSpace="calibratedRGB"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Location Count Label" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="csF-KS-xGE">
<rect key="frame" x="16" y="48" width="343" height="20.5"/>
<color key="backgroundColor" red="0.80000001190000003" green="0.80000001190000003" blue="0.80000001190000003" alpha="1" colorSpace="calibratedRGB"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Location String" lineBreakMode="tailTruncation" numberOfLines="8" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="qOc-gk-gSp">
<rect key="frame" x="16" y="76" width="343" height="20.5"/>
<color key="backgroundColor" red="0.80000001190000003" green="0.80000001190000003" blue="0.80000001190000003" alpha="1" colorSpace="calibratedRGB"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Placemark String" lineBreakMode="tailTruncation" numberOfLines="14" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="42A-nO-tNf">
<rect key="frame" x="16" y="104" width="343" height="20.5"/>
<color key="backgroundColor" red="0.80000001190000003" green="0.80000001190000003" blue="0.80000001190000003" alpha="1" colorSpace="calibratedRGB"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="HgN-oB-ds0">
<rect key="frame" x="121.5" y="578" width="132" height="30"/>
<state key="normal" title="Request Placemark"/>
<connections>
<action selector="RefreshLocationButton:" destination="BYZ-38-t0r" eventType="touchUpInside" id="izY-S5-wjg"/>
</connections>
</button>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="ZIg-u9-TMR" firstAttribute="leading" secondItem="6Tk-OE-BBY" secondAttribute="leading" constant="16" id="6HO-kN-l1z"/>
<constraint firstItem="qOc-gk-gSp" firstAttribute="top" secondItem="csF-KS-xGE" secondAttribute="bottom" constant="7.5" id="6ux-dx-gJr"/>
<constraint firstItem="6Tk-OE-BBY" firstAttribute="trailing" secondItem="42A-nO-tNf" secondAttribute="trailing" constant="16" id="8dG-gV-Cob"/>
<constraint firstItem="HgN-oB-ds0" firstAttribute="centerX" secondItem="8bC-Xf-vdC" secondAttribute="centerX" id="A38-Nt-i3D"/>
<constraint firstItem="6Tk-OE-BBY" firstAttribute="trailing" secondItem="ZIg-u9-TMR" secondAttribute="trailing" constant="16" id="Bb0-YC-oov"/>
<constraint firstItem="csF-KS-xGE" firstAttribute="leading" secondItem="6Tk-OE-BBY" secondAttribute="leading" constant="16" id="FJU-ha-HkL"/>
<constraint firstItem="42A-nO-tNf" firstAttribute="top" secondItem="qOc-gk-gSp" secondAttribute="bottom" constant="7.5" id="SpR-XB-MLG"/>
<constraint firstItem="6Tk-OE-BBY" firstAttribute="bottom" secondItem="HgN-oB-ds0" secondAttribute="bottom" constant="59" id="Vr6-QE-230"/>
<constraint firstItem="42A-nO-tNf" firstAttribute="leading" secondItem="6Tk-OE-BBY" secondAttribute="leading" constant="16" id="aHo-kJ-aCb"/>
<constraint firstItem="csF-KS-xGE" firstAttribute="top" secondItem="ZIg-u9-TMR" secondAttribute="bottom" constant="7.5" id="c63-Mq-ItW"/>
<constraint firstItem="6Tk-OE-BBY" firstAttribute="trailing" secondItem="csF-KS-xGE" secondAttribute="trailing" constant="16" id="dlV-Hc-8XJ"/>
<constraint firstItem="qOc-gk-gSp" firstAttribute="leading" secondItem="6Tk-OE-BBY" secondAttribute="leading" constant="16" id="m5y-Q8-jxI"/>
<constraint firstItem="ZIg-u9-TMR" firstAttribute="top" secondItem="6Tk-OE-BBY" secondAttribute="top" id="sdw-WQ-Bx9"/>
<constraint firstItem="6Tk-OE-BBY" firstAttribute="trailing" secondItem="qOc-gk-gSp" secondAttribute="trailing" constant="16" id="woB-ig-i5v"/>
</constraints>
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
</view>
<connections>
<outlet property="LocationCounterLabel" destination="ZIg-u9-TMR" id="K4g-WT-f82"/>
<outlet property="LocationLabel" destination="qOc-gk-gSp" id="Cdw-bw-EWt"/>
<outlet property="PlacemarkLabel" destination="42A-nO-tNf" id="dMh-bw-cRE"/>
<outlet property="RequestCounterLabel" destination="csF-KS-xGE" id="ai6-zn-Toi"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53.600000000000001" y="66.11694152923539"/>
</scene>
</scenes>
</document>





share|improve this answer

























    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f46869394%2freverse-geocoding-in-swift-4%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    21














    import UIKit
    import CoreLocation
    import PlaygroundSupport
    PlaygroundPage.current.needsIndefiniteExecution = true




    func geocode(latitude: Double, longitude: Double, completion: @escaping (_ placemark: [CLPlacemark]?, _ error: Error?) -> Void)  {
    CLGeocoder().reverseGeocodeLocation(CLLocation(latitude: latitude, longitude: longitude)) { placemark, error in
    guard let placemark = placemark, error == nil else {
    completion(nil, error)
    return
    }
    completion(placemark, nil)
    }
    }


    or simply:



    func geocode(latitude: Double, longitude: Double, completion: @escaping (_ placemark: [CLPlacemark]?, _ error: Error?) -> Void)  {
    CLGeocoder().reverseGeocodeLocation(CLLocation(latitude: latitude, longitude: longitude), completionHandler: completion)
    }


    or extending CLLocation:



    extension CLLocation {
    func geocode(completion: @escaping (_ placemark: [CLPlacemark]?, _ error: Error?) -> Void) {
    CLGeocoder().reverseGeocodeLocation(self, completionHandler: completion)
    }
    }




    To format your place mark as a mailing address you can use Contacts framework CNPostalAddressFormatter:



    import Contacts

    extension Formatter {
    static let mailingAddress: CNPostalAddressFormatter = {
    let formatter = CNPostalAddressFormatter()
    formatter.style = .mailingAddress
    return formatter
    }()
    }

    extension CLPlacemark {
    var mailingAddress: String? {
    return postalAddress?.mailingAddress
    }
    }

    extension CNPostalAddress {
    var mailingAddress: String {
    return Formatter.mailingAddress.string(from: self)
    }
    }





    placemark



    Contains an array of CLPlacemark objects. For most geocoding requests,
    this array should contain only one entry. However, forward-geocoding
    requests may return multiple placemark objects in situations where the
    specified address could not be resolved to a single location. If the
    request was canceled or there was an error in obtaining the placemark
    information, this parameter is nil.




    For more information about the CLPlacemark properties you can check this CLPlacemark





    Usage:



    let location = CLLocation(latitude: -22.963451, longitude: -43.198242)
    location.geocode { placemark, error in
    if let error = error as? CLError {
    print("CLError:", error)
    return
    } else if let placemark = placemark?.first {
    // you should always update your UI in the main thread
    DispatchQueue.main.async {
    // update UI here
    print("name:", placemark.name ?? "unknown")

    print("address1:", placemark.thoroughfare ?? "unknown")
    print("address2:", placemark.subThoroughfare ?? "unknown")
    print("neighborhood:", placemark.subLocality ?? "unknown")
    print("city:", placemark.locality ?? "unknown")

    print("state:", placemark.administrativeArea ?? "unknown")
    print("subAdministrativeArea:", placemark.subAdministrativeArea ?? "unknown")
    print("zip code:", placemark.postalCode ?? "unknown")
    print("country:", placemark.country ?? "unknown", terminator: "nn")

    print("isoCountryCode:", placemark.isoCountryCode ?? "unknown")
    print("region identifier:", placemark.region?.identifier ?? "unknown")

    print("timezone:", placemark.timeZone ?? "unknown", terminator:"nn")

    // Mailind Address
    print(placemark.mailingAddress ?? "unknown")
    }
    }
    }




    This will print



    name: Morro da Saudade
    address1: Rua Casuarina
    address2: 597
    neighborhood: Lagoa
    city: Rio de Janeiro
    state: RJ
    subAdministrativeArea: unknown
    zip code: 22011-040
    country: Brazil

    isoCountryCode: BR
    region identifier: <-22.96345100,-43.19824200> radius 141.83
    timezone: America/Sao_Paulo (current)



    Rua Casuarina, 597



    Lagoa



    Rio de Janeiro RJ



    22011-040



    Brazil







    share|improve this answer


























    • Thank you! This gets the job done. I don't think I'm going to be able to declare a let constant like this, given it's async code. I'll refactor this let myPlacemark = geocode(latitude: 37.3318, longitude: 122.0312) with something else.

      – Adrian
      Oct 22 '17 at 1:25











    • You need to use it inside the closure

      – Leo Dabus
      Oct 22 '17 at 1:26











    • Perfect. Thank you!

      – Adrian
      Oct 22 '17 at 1:29











    • HI, How to get the complete state name?, not in ISO code format.

      – Ramakrishna
      Jan 6 '18 at 11:22
















    21














    import UIKit
    import CoreLocation
    import PlaygroundSupport
    PlaygroundPage.current.needsIndefiniteExecution = true




    func geocode(latitude: Double, longitude: Double, completion: @escaping (_ placemark: [CLPlacemark]?, _ error: Error?) -> Void)  {
    CLGeocoder().reverseGeocodeLocation(CLLocation(latitude: latitude, longitude: longitude)) { placemark, error in
    guard let placemark = placemark, error == nil else {
    completion(nil, error)
    return
    }
    completion(placemark, nil)
    }
    }


    or simply:



    func geocode(latitude: Double, longitude: Double, completion: @escaping (_ placemark: [CLPlacemark]?, _ error: Error?) -> Void)  {
    CLGeocoder().reverseGeocodeLocation(CLLocation(latitude: latitude, longitude: longitude), completionHandler: completion)
    }


    or extending CLLocation:



    extension CLLocation {
    func geocode(completion: @escaping (_ placemark: [CLPlacemark]?, _ error: Error?) -> Void) {
    CLGeocoder().reverseGeocodeLocation(self, completionHandler: completion)
    }
    }




    To format your place mark as a mailing address you can use Contacts framework CNPostalAddressFormatter:



    import Contacts

    extension Formatter {
    static let mailingAddress: CNPostalAddressFormatter = {
    let formatter = CNPostalAddressFormatter()
    formatter.style = .mailingAddress
    return formatter
    }()
    }

    extension CLPlacemark {
    var mailingAddress: String? {
    return postalAddress?.mailingAddress
    }
    }

    extension CNPostalAddress {
    var mailingAddress: String {
    return Formatter.mailingAddress.string(from: self)
    }
    }





    placemark



    Contains an array of CLPlacemark objects. For most geocoding requests,
    this array should contain only one entry. However, forward-geocoding
    requests may return multiple placemark objects in situations where the
    specified address could not be resolved to a single location. If the
    request was canceled or there was an error in obtaining the placemark
    information, this parameter is nil.




    For more information about the CLPlacemark properties you can check this CLPlacemark





    Usage:



    let location = CLLocation(latitude: -22.963451, longitude: -43.198242)
    location.geocode { placemark, error in
    if let error = error as? CLError {
    print("CLError:", error)
    return
    } else if let placemark = placemark?.first {
    // you should always update your UI in the main thread
    DispatchQueue.main.async {
    // update UI here
    print("name:", placemark.name ?? "unknown")

    print("address1:", placemark.thoroughfare ?? "unknown")
    print("address2:", placemark.subThoroughfare ?? "unknown")
    print("neighborhood:", placemark.subLocality ?? "unknown")
    print("city:", placemark.locality ?? "unknown")

    print("state:", placemark.administrativeArea ?? "unknown")
    print("subAdministrativeArea:", placemark.subAdministrativeArea ?? "unknown")
    print("zip code:", placemark.postalCode ?? "unknown")
    print("country:", placemark.country ?? "unknown", terminator: "nn")

    print("isoCountryCode:", placemark.isoCountryCode ?? "unknown")
    print("region identifier:", placemark.region?.identifier ?? "unknown")

    print("timezone:", placemark.timeZone ?? "unknown", terminator:"nn")

    // Mailind Address
    print(placemark.mailingAddress ?? "unknown")
    }
    }
    }




    This will print



    name: Morro da Saudade
    address1: Rua Casuarina
    address2: 597
    neighborhood: Lagoa
    city: Rio de Janeiro
    state: RJ
    subAdministrativeArea: unknown
    zip code: 22011-040
    country: Brazil

    isoCountryCode: BR
    region identifier: <-22.96345100,-43.19824200> radius 141.83
    timezone: America/Sao_Paulo (current)



    Rua Casuarina, 597



    Lagoa



    Rio de Janeiro RJ



    22011-040



    Brazil







    share|improve this answer


























    • Thank you! This gets the job done. I don't think I'm going to be able to declare a let constant like this, given it's async code. I'll refactor this let myPlacemark = geocode(latitude: 37.3318, longitude: 122.0312) with something else.

      – Adrian
      Oct 22 '17 at 1:25











    • You need to use it inside the closure

      – Leo Dabus
      Oct 22 '17 at 1:26











    • Perfect. Thank you!

      – Adrian
      Oct 22 '17 at 1:29











    • HI, How to get the complete state name?, not in ISO code format.

      – Ramakrishna
      Jan 6 '18 at 11:22














    21












    21








    21







    import UIKit
    import CoreLocation
    import PlaygroundSupport
    PlaygroundPage.current.needsIndefiniteExecution = true




    func geocode(latitude: Double, longitude: Double, completion: @escaping (_ placemark: [CLPlacemark]?, _ error: Error?) -> Void)  {
    CLGeocoder().reverseGeocodeLocation(CLLocation(latitude: latitude, longitude: longitude)) { placemark, error in
    guard let placemark = placemark, error == nil else {
    completion(nil, error)
    return
    }
    completion(placemark, nil)
    }
    }


    or simply:



    func geocode(latitude: Double, longitude: Double, completion: @escaping (_ placemark: [CLPlacemark]?, _ error: Error?) -> Void)  {
    CLGeocoder().reverseGeocodeLocation(CLLocation(latitude: latitude, longitude: longitude), completionHandler: completion)
    }


    or extending CLLocation:



    extension CLLocation {
    func geocode(completion: @escaping (_ placemark: [CLPlacemark]?, _ error: Error?) -> Void) {
    CLGeocoder().reverseGeocodeLocation(self, completionHandler: completion)
    }
    }




    To format your place mark as a mailing address you can use Contacts framework CNPostalAddressFormatter:



    import Contacts

    extension Formatter {
    static let mailingAddress: CNPostalAddressFormatter = {
    let formatter = CNPostalAddressFormatter()
    formatter.style = .mailingAddress
    return formatter
    }()
    }

    extension CLPlacemark {
    var mailingAddress: String? {
    return postalAddress?.mailingAddress
    }
    }

    extension CNPostalAddress {
    var mailingAddress: String {
    return Formatter.mailingAddress.string(from: self)
    }
    }





    placemark



    Contains an array of CLPlacemark objects. For most geocoding requests,
    this array should contain only one entry. However, forward-geocoding
    requests may return multiple placemark objects in situations where the
    specified address could not be resolved to a single location. If the
    request was canceled or there was an error in obtaining the placemark
    information, this parameter is nil.




    For more information about the CLPlacemark properties you can check this CLPlacemark





    Usage:



    let location = CLLocation(latitude: -22.963451, longitude: -43.198242)
    location.geocode { placemark, error in
    if let error = error as? CLError {
    print("CLError:", error)
    return
    } else if let placemark = placemark?.first {
    // you should always update your UI in the main thread
    DispatchQueue.main.async {
    // update UI here
    print("name:", placemark.name ?? "unknown")

    print("address1:", placemark.thoroughfare ?? "unknown")
    print("address2:", placemark.subThoroughfare ?? "unknown")
    print("neighborhood:", placemark.subLocality ?? "unknown")
    print("city:", placemark.locality ?? "unknown")

    print("state:", placemark.administrativeArea ?? "unknown")
    print("subAdministrativeArea:", placemark.subAdministrativeArea ?? "unknown")
    print("zip code:", placemark.postalCode ?? "unknown")
    print("country:", placemark.country ?? "unknown", terminator: "nn")

    print("isoCountryCode:", placemark.isoCountryCode ?? "unknown")
    print("region identifier:", placemark.region?.identifier ?? "unknown")

    print("timezone:", placemark.timeZone ?? "unknown", terminator:"nn")

    // Mailind Address
    print(placemark.mailingAddress ?? "unknown")
    }
    }
    }




    This will print



    name: Morro da Saudade
    address1: Rua Casuarina
    address2: 597
    neighborhood: Lagoa
    city: Rio de Janeiro
    state: RJ
    subAdministrativeArea: unknown
    zip code: 22011-040
    country: Brazil

    isoCountryCode: BR
    region identifier: <-22.96345100,-43.19824200> radius 141.83
    timezone: America/Sao_Paulo (current)



    Rua Casuarina, 597



    Lagoa



    Rio de Janeiro RJ



    22011-040



    Brazil







    share|improve this answer















    import UIKit
    import CoreLocation
    import PlaygroundSupport
    PlaygroundPage.current.needsIndefiniteExecution = true




    func geocode(latitude: Double, longitude: Double, completion: @escaping (_ placemark: [CLPlacemark]?, _ error: Error?) -> Void)  {
    CLGeocoder().reverseGeocodeLocation(CLLocation(latitude: latitude, longitude: longitude)) { placemark, error in
    guard let placemark = placemark, error == nil else {
    completion(nil, error)
    return
    }
    completion(placemark, nil)
    }
    }


    or simply:



    func geocode(latitude: Double, longitude: Double, completion: @escaping (_ placemark: [CLPlacemark]?, _ error: Error?) -> Void)  {
    CLGeocoder().reverseGeocodeLocation(CLLocation(latitude: latitude, longitude: longitude), completionHandler: completion)
    }


    or extending CLLocation:



    extension CLLocation {
    func geocode(completion: @escaping (_ placemark: [CLPlacemark]?, _ error: Error?) -> Void) {
    CLGeocoder().reverseGeocodeLocation(self, completionHandler: completion)
    }
    }




    To format your place mark as a mailing address you can use Contacts framework CNPostalAddressFormatter:



    import Contacts

    extension Formatter {
    static let mailingAddress: CNPostalAddressFormatter = {
    let formatter = CNPostalAddressFormatter()
    formatter.style = .mailingAddress
    return formatter
    }()
    }

    extension CLPlacemark {
    var mailingAddress: String? {
    return postalAddress?.mailingAddress
    }
    }

    extension CNPostalAddress {
    var mailingAddress: String {
    return Formatter.mailingAddress.string(from: self)
    }
    }





    placemark



    Contains an array of CLPlacemark objects. For most geocoding requests,
    this array should contain only one entry. However, forward-geocoding
    requests may return multiple placemark objects in situations where the
    specified address could not be resolved to a single location. If the
    request was canceled or there was an error in obtaining the placemark
    information, this parameter is nil.




    For more information about the CLPlacemark properties you can check this CLPlacemark





    Usage:



    let location = CLLocation(latitude: -22.963451, longitude: -43.198242)
    location.geocode { placemark, error in
    if let error = error as? CLError {
    print("CLError:", error)
    return
    } else if let placemark = placemark?.first {
    // you should always update your UI in the main thread
    DispatchQueue.main.async {
    // update UI here
    print("name:", placemark.name ?? "unknown")

    print("address1:", placemark.thoroughfare ?? "unknown")
    print("address2:", placemark.subThoroughfare ?? "unknown")
    print("neighborhood:", placemark.subLocality ?? "unknown")
    print("city:", placemark.locality ?? "unknown")

    print("state:", placemark.administrativeArea ?? "unknown")
    print("subAdministrativeArea:", placemark.subAdministrativeArea ?? "unknown")
    print("zip code:", placemark.postalCode ?? "unknown")
    print("country:", placemark.country ?? "unknown", terminator: "nn")

    print("isoCountryCode:", placemark.isoCountryCode ?? "unknown")
    print("region identifier:", placemark.region?.identifier ?? "unknown")

    print("timezone:", placemark.timeZone ?? "unknown", terminator:"nn")

    // Mailind Address
    print(placemark.mailingAddress ?? "unknown")
    }
    }
    }




    This will print



    name: Morro da Saudade
    address1: Rua Casuarina
    address2: 597
    neighborhood: Lagoa
    city: Rio de Janeiro
    state: RJ
    subAdministrativeArea: unknown
    zip code: 22011-040
    country: Brazil

    isoCountryCode: BR
    region identifier: <-22.96345100,-43.19824200> radius 141.83
    timezone: America/Sao_Paulo (current)



    Rua Casuarina, 597



    Lagoa



    Rio de Janeiro RJ



    22011-040



    Brazil








    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Feb 18 at 18:57

























    answered Oct 22 '17 at 0:57









    Leo DabusLeo Dabus

    135k32277351




    135k32277351













    • Thank you! This gets the job done. I don't think I'm going to be able to declare a let constant like this, given it's async code. I'll refactor this let myPlacemark = geocode(latitude: 37.3318, longitude: 122.0312) with something else.

      – Adrian
      Oct 22 '17 at 1:25











    • You need to use it inside the closure

      – Leo Dabus
      Oct 22 '17 at 1:26











    • Perfect. Thank you!

      – Adrian
      Oct 22 '17 at 1:29











    • HI, How to get the complete state name?, not in ISO code format.

      – Ramakrishna
      Jan 6 '18 at 11:22



















    • Thank you! This gets the job done. I don't think I'm going to be able to declare a let constant like this, given it's async code. I'll refactor this let myPlacemark = geocode(latitude: 37.3318, longitude: 122.0312) with something else.

      – Adrian
      Oct 22 '17 at 1:25











    • You need to use it inside the closure

      – Leo Dabus
      Oct 22 '17 at 1:26











    • Perfect. Thank you!

      – Adrian
      Oct 22 '17 at 1:29











    • HI, How to get the complete state name?, not in ISO code format.

      – Ramakrishna
      Jan 6 '18 at 11:22

















    Thank you! This gets the job done. I don't think I'm going to be able to declare a let constant like this, given it's async code. I'll refactor this let myPlacemark = geocode(latitude: 37.3318, longitude: 122.0312) with something else.

    – Adrian
    Oct 22 '17 at 1:25





    Thank you! This gets the job done. I don't think I'm going to be able to declare a let constant like this, given it's async code. I'll refactor this let myPlacemark = geocode(latitude: 37.3318, longitude: 122.0312) with something else.

    – Adrian
    Oct 22 '17 at 1:25













    You need to use it inside the closure

    – Leo Dabus
    Oct 22 '17 at 1:26





    You need to use it inside the closure

    – Leo Dabus
    Oct 22 '17 at 1:26













    Perfect. Thank you!

    – Adrian
    Oct 22 '17 at 1:29





    Perfect. Thank you!

    – Adrian
    Oct 22 '17 at 1:29













    HI, How to get the complete state name?, not in ISO code format.

    – Ramakrishna
    Jan 6 '18 at 11:22





    HI, How to get the complete state name?, not in ISO code format.

    – Ramakrishna
    Jan 6 '18 at 11:22













    0














    There are so many questions dealing with 'reverseGeocodeLocation' on Stack Overflow, I've seen so many of them. I'm using Swift 4.2 and I thought my 'reverseGeocodeLocation' requests might be timing out. Well, this is NOT the case, when starting to move with an iPhone the 'didUpdateLocations' cycles need to mature. It can take two or more cycles before 'reverseGeocodeLocation' returns placemarks.



    I wrote a simple app that uses 'reverseGeocodeLocation' until 'placemarks' are returned after repeated 'didUpdateLocations' cycles. This is my own home grown 'SampleCode'. I learned a lot from using the app, it might help others understand how reverse geocode requests work in the real world.



    Please give your comments on possible improvements. This code is freely given and freely taken.



    import Foundation
    import UIKit
    import CoreLocation

    class ViewController: UIViewController, CLLocationManagerDelegate {
    @IBAction func RefreshLocationButton(_ sender: Any) {
    self.requestingPlacemark = true
    self.placemarkData = nil
    //^Make another Placemark Request
    self.requestCounter = 0
    self.RequestCounterLabel.text = ""
    self.LocationLabel.text = ""
    self.PlacemarkLabel.text = ""}
    @IBOutlet weak var LocationCounterLabel: UILabel!
    @IBOutlet weak var RequestCounterLabel: UILabel!
    @IBOutlet weak var LocationLabel: UILabel!
    @IBOutlet weak var PlacemarkLabel: UILabel!
    let locationManager = CLLocationManager()
    var placemarkData: CLPlacemark!
    var placemarkString: String!
    var printPlacemarkData: Bool!
    var didUpdateLocationsCounter: Int = 0
    var requestCounter: Int = 0
    var requestingPlacemark: Bool = true

    override func viewDidLoad() {
    super.viewDidLoad()
    if CLLocationManager.locationServicesEnabled() {
    locationManager.requestAlwaysAuthorization()
    locationManager.delegate = self
    //locationManager.desiredAccuracy = kCLLocationAccuracyBest
    locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation
    locationManager.startUpdatingLocation()
    self.RequestCounterLabel.text = ""
    self.LocationLabel.text = ""
    self.PlacemarkLabel.text = ""}}
    func printPlacemarks() {
    if printPlacemarkData {
    self.placemarkString = "Placemark Data:"
    self.placemarkString = buildPlacemarkString(item: 1)
    self.placemarkString = buildPlacemarkString(item: 2)
    self.placemarkString = buildPlacemarkString(item: 3)
    self.placemarkString = buildPlacemarkString(item: 4)
    self.placemarkString = buildPlacemarkString(item: 5)
    self.placemarkString = buildPlacemarkString(item: 6)
    self.placemarkString = buildPlacemarkString(item: 7)
    self.placemarkString = buildPlacemarkString(item: 8)
    self.placemarkString = buildPlacemarkString(item: 9)
    self.placemarkString = buildPlacemarkString(item: 10)
    self.PlacemarkLabel.text = self.placemarkString
    self.printPlacemarkData = false}}
    func buildPlacemarkString(item: Int) -> String {
    var elementText: String!
    var newString: String!
    switch item {
    case 1: elementText = "name: " + self.placemarkData.name!
    case 2: elementText = "subThoroughfare: " + self.placemarkData.subThoroughfare!
    case 3: elementText = "thoroughfare: " + self.placemarkData.thoroughfare!
    case 4: elementText = "postalCode: " + self.placemarkData.postalCode!
    case 5: elementText = "subLocality: " + self.placemarkData.subLocality!
    case 6: elementText = "locality: " + self.placemarkData.locality!
    case 7: elementText = "subAdministrativeArea: " + self.placemarkData.subAdministrativeArea!
    case 8: elementText = "administrativeArea: " + self.placemarkData.administrativeArea!
    case 9: elementText = "country: " + self.placemarkData.country!
    case 10: elementText = "isoCountryCode: " + self.placemarkData.isoCountryCode!
    default: print("Error: incorrect item number!")}
    newString = self.placemarkString + "n" + elementText
    return newString
    }
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    //location prints one time and 'didUpdateLocations' is stopped:
    self.didUpdateLocationsCounter = self.didUpdateLocationsCounter + 1
    let labelString = String(describing: self.didUpdateLocationsCounter)
    self.LocationCounterLabel.text = "Location Update Counter: " + labelString
    if self.placemarkData == nil {
    //location variable:
    self.requestCounter = self.requestCounter + 1
    let textString = String(describing: self.requestCounter)
    self.RequestCounterLabel.text = "Request Counter: " + textString
    if locations.count == 0 {
    self.LocationLabel.text = "Locations: There was NONE"}
    else {
    if locations.count > 0 {
    let coordinate2D: CLLocation = locations.first!
    let location = CLLocation(latitude: coordinate2D.coordinate.latitude, longitude: coordinate2D.coordinate.longitude)
    let printString = String(describing: location)
    self.LocationLabel.text = "Location: " + printString
    let geocoder: CLGeocoder = CLGeocoder()
    geocoder.reverseGeocodeLocation(location, completionHandler: {(placemarks, error) -> Void in
    if error != nil {
    let errorString = String(describing: error?.localizedDescription)
    print("reverse geodcode fail: (errorString)")
    self.LocationCounterLabel.text = ""
    self.RequestCounterLabel.text = ""
    self.LocationLabel.text = "Reverse Geodcode fail: (errorString)"
    self.PlacemarkLabel.text = ""
    self.requestingPlacemark = false
    return}
    else {
    let pm = placemarks! as [CLPlacemark]
    //There is ALWAYS 'placemarks' Data
    if pm.count > 0 {
    self.placemarkData = placemarks![0]
    self.printPlacemarkData = true
    self.printPlacemarks()
    self.requestingPlacemark = false}}})}
    else {
    if self.requestingPlacemark {
    self.LocationLabel.text = "Problem: There is no 'location.first'"}}}}}}


    And then the Storyboard UI:



    Storyboard Image



    View Controller Image



    <?xml version="1.0" encoding="UTF-8"?>
    <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
    <device id="retina4_7" orientation="portrait">
    <adaptation id="fullscreen"/>
    </device>
    <dependencies>
    <deployment identifier="iOS"/>
    <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14460.20"/>
    <capability name="Safe area layout guides" minToolsVersion="9.0"/>
    <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
    </dependencies>
    <scenes>
    <!--View Controller-->
    <scene sceneID="tne-QT-ifu">
    <objects>
    <viewController id="BYZ-38-t0r" customClass="ViewController" customModule="MyThoroughfare" customModuleProvider="target" sceneMemberID="viewController">
    <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
    <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
    <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
    <subviews>
    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Location Counter" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ZIg-u9-TMR">
    <rect key="frame" x="16" y="20" width="343" height="20.5"/>
    <color key="backgroundColor" red="0.80000001190000003" green="0.80000001190000003" blue="0.80000001190000003" alpha="1" colorSpace="calibratedRGB"/>
    <fontDescription key="fontDescription" type="system" pointSize="17"/>
    <nil key="textColor"/>
    <nil key="highlightedColor"/>
    </label>
    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Location Count Label" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="csF-KS-xGE">
    <rect key="frame" x="16" y="48" width="343" height="20.5"/>
    <color key="backgroundColor" red="0.80000001190000003" green="0.80000001190000003" blue="0.80000001190000003" alpha="1" colorSpace="calibratedRGB"/>
    <fontDescription key="fontDescription" type="system" pointSize="17"/>
    <nil key="textColor"/>
    <nil key="highlightedColor"/>
    </label>
    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Location String" lineBreakMode="tailTruncation" numberOfLines="8" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="qOc-gk-gSp">
    <rect key="frame" x="16" y="76" width="343" height="20.5"/>
    <color key="backgroundColor" red="0.80000001190000003" green="0.80000001190000003" blue="0.80000001190000003" alpha="1" colorSpace="calibratedRGB"/>
    <fontDescription key="fontDescription" type="system" pointSize="17"/>
    <nil key="textColor"/>
    <nil key="highlightedColor"/>
    </label>
    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Placemark String" lineBreakMode="tailTruncation" numberOfLines="14" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="42A-nO-tNf">
    <rect key="frame" x="16" y="104" width="343" height="20.5"/>
    <color key="backgroundColor" red="0.80000001190000003" green="0.80000001190000003" blue="0.80000001190000003" alpha="1" colorSpace="calibratedRGB"/>
    <fontDescription key="fontDescription" type="system" pointSize="17"/>
    <nil key="textColor"/>
    <nil key="highlightedColor"/>
    </label>
    <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="HgN-oB-ds0">
    <rect key="frame" x="121.5" y="578" width="132" height="30"/>
    <state key="normal" title="Request Placemark"/>
    <connections>
    <action selector="RefreshLocationButton:" destination="BYZ-38-t0r" eventType="touchUpInside" id="izY-S5-wjg"/>
    </connections>
    </button>
    </subviews>
    <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
    <constraints>
    <constraint firstItem="ZIg-u9-TMR" firstAttribute="leading" secondItem="6Tk-OE-BBY" secondAttribute="leading" constant="16" id="6HO-kN-l1z"/>
    <constraint firstItem="qOc-gk-gSp" firstAttribute="top" secondItem="csF-KS-xGE" secondAttribute="bottom" constant="7.5" id="6ux-dx-gJr"/>
    <constraint firstItem="6Tk-OE-BBY" firstAttribute="trailing" secondItem="42A-nO-tNf" secondAttribute="trailing" constant="16" id="8dG-gV-Cob"/>
    <constraint firstItem="HgN-oB-ds0" firstAttribute="centerX" secondItem="8bC-Xf-vdC" secondAttribute="centerX" id="A38-Nt-i3D"/>
    <constraint firstItem="6Tk-OE-BBY" firstAttribute="trailing" secondItem="ZIg-u9-TMR" secondAttribute="trailing" constant="16" id="Bb0-YC-oov"/>
    <constraint firstItem="csF-KS-xGE" firstAttribute="leading" secondItem="6Tk-OE-BBY" secondAttribute="leading" constant="16" id="FJU-ha-HkL"/>
    <constraint firstItem="42A-nO-tNf" firstAttribute="top" secondItem="qOc-gk-gSp" secondAttribute="bottom" constant="7.5" id="SpR-XB-MLG"/>
    <constraint firstItem="6Tk-OE-BBY" firstAttribute="bottom" secondItem="HgN-oB-ds0" secondAttribute="bottom" constant="59" id="Vr6-QE-230"/>
    <constraint firstItem="42A-nO-tNf" firstAttribute="leading" secondItem="6Tk-OE-BBY" secondAttribute="leading" constant="16" id="aHo-kJ-aCb"/>
    <constraint firstItem="csF-KS-xGE" firstAttribute="top" secondItem="ZIg-u9-TMR" secondAttribute="bottom" constant="7.5" id="c63-Mq-ItW"/>
    <constraint firstItem="6Tk-OE-BBY" firstAttribute="trailing" secondItem="csF-KS-xGE" secondAttribute="trailing" constant="16" id="dlV-Hc-8XJ"/>
    <constraint firstItem="qOc-gk-gSp" firstAttribute="leading" secondItem="6Tk-OE-BBY" secondAttribute="leading" constant="16" id="m5y-Q8-jxI"/>
    <constraint firstItem="ZIg-u9-TMR" firstAttribute="top" secondItem="6Tk-OE-BBY" secondAttribute="top" id="sdw-WQ-Bx9"/>
    <constraint firstItem="6Tk-OE-BBY" firstAttribute="trailing" secondItem="qOc-gk-gSp" secondAttribute="trailing" constant="16" id="woB-ig-i5v"/>
    </constraints>
    <viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
    </view>
    <connections>
    <outlet property="LocationCounterLabel" destination="ZIg-u9-TMR" id="K4g-WT-f82"/>
    <outlet property="LocationLabel" destination="qOc-gk-gSp" id="Cdw-bw-EWt"/>
    <outlet property="PlacemarkLabel" destination="42A-nO-tNf" id="dMh-bw-cRE"/>
    <outlet property="RequestCounterLabel" destination="csF-KS-xGE" id="ai6-zn-Toi"/>
    </connections>
    </viewController>
    <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
    </objects>
    <point key="canvasLocation" x="53.600000000000001" y="66.11694152923539"/>
    </scene>
    </scenes>
    </document>





    share|improve this answer






























      0














      There are so many questions dealing with 'reverseGeocodeLocation' on Stack Overflow, I've seen so many of them. I'm using Swift 4.2 and I thought my 'reverseGeocodeLocation' requests might be timing out. Well, this is NOT the case, when starting to move with an iPhone the 'didUpdateLocations' cycles need to mature. It can take two or more cycles before 'reverseGeocodeLocation' returns placemarks.



      I wrote a simple app that uses 'reverseGeocodeLocation' until 'placemarks' are returned after repeated 'didUpdateLocations' cycles. This is my own home grown 'SampleCode'. I learned a lot from using the app, it might help others understand how reverse geocode requests work in the real world.



      Please give your comments on possible improvements. This code is freely given and freely taken.



      import Foundation
      import UIKit
      import CoreLocation

      class ViewController: UIViewController, CLLocationManagerDelegate {
      @IBAction func RefreshLocationButton(_ sender: Any) {
      self.requestingPlacemark = true
      self.placemarkData = nil
      //^Make another Placemark Request
      self.requestCounter = 0
      self.RequestCounterLabel.text = ""
      self.LocationLabel.text = ""
      self.PlacemarkLabel.text = ""}
      @IBOutlet weak var LocationCounterLabel: UILabel!
      @IBOutlet weak var RequestCounterLabel: UILabel!
      @IBOutlet weak var LocationLabel: UILabel!
      @IBOutlet weak var PlacemarkLabel: UILabel!
      let locationManager = CLLocationManager()
      var placemarkData: CLPlacemark!
      var placemarkString: String!
      var printPlacemarkData: Bool!
      var didUpdateLocationsCounter: Int = 0
      var requestCounter: Int = 0
      var requestingPlacemark: Bool = true

      override func viewDidLoad() {
      super.viewDidLoad()
      if CLLocationManager.locationServicesEnabled() {
      locationManager.requestAlwaysAuthorization()
      locationManager.delegate = self
      //locationManager.desiredAccuracy = kCLLocationAccuracyBest
      locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation
      locationManager.startUpdatingLocation()
      self.RequestCounterLabel.text = ""
      self.LocationLabel.text = ""
      self.PlacemarkLabel.text = ""}}
      func printPlacemarks() {
      if printPlacemarkData {
      self.placemarkString = "Placemark Data:"
      self.placemarkString = buildPlacemarkString(item: 1)
      self.placemarkString = buildPlacemarkString(item: 2)
      self.placemarkString = buildPlacemarkString(item: 3)
      self.placemarkString = buildPlacemarkString(item: 4)
      self.placemarkString = buildPlacemarkString(item: 5)
      self.placemarkString = buildPlacemarkString(item: 6)
      self.placemarkString = buildPlacemarkString(item: 7)
      self.placemarkString = buildPlacemarkString(item: 8)
      self.placemarkString = buildPlacemarkString(item: 9)
      self.placemarkString = buildPlacemarkString(item: 10)
      self.PlacemarkLabel.text = self.placemarkString
      self.printPlacemarkData = false}}
      func buildPlacemarkString(item: Int) -> String {
      var elementText: String!
      var newString: String!
      switch item {
      case 1: elementText = "name: " + self.placemarkData.name!
      case 2: elementText = "subThoroughfare: " + self.placemarkData.subThoroughfare!
      case 3: elementText = "thoroughfare: " + self.placemarkData.thoroughfare!
      case 4: elementText = "postalCode: " + self.placemarkData.postalCode!
      case 5: elementText = "subLocality: " + self.placemarkData.subLocality!
      case 6: elementText = "locality: " + self.placemarkData.locality!
      case 7: elementText = "subAdministrativeArea: " + self.placemarkData.subAdministrativeArea!
      case 8: elementText = "administrativeArea: " + self.placemarkData.administrativeArea!
      case 9: elementText = "country: " + self.placemarkData.country!
      case 10: elementText = "isoCountryCode: " + self.placemarkData.isoCountryCode!
      default: print("Error: incorrect item number!")}
      newString = self.placemarkString + "n" + elementText
      return newString
      }
      func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
      //location prints one time and 'didUpdateLocations' is stopped:
      self.didUpdateLocationsCounter = self.didUpdateLocationsCounter + 1
      let labelString = String(describing: self.didUpdateLocationsCounter)
      self.LocationCounterLabel.text = "Location Update Counter: " + labelString
      if self.placemarkData == nil {
      //location variable:
      self.requestCounter = self.requestCounter + 1
      let textString = String(describing: self.requestCounter)
      self.RequestCounterLabel.text = "Request Counter: " + textString
      if locations.count == 0 {
      self.LocationLabel.text = "Locations: There was NONE"}
      else {
      if locations.count > 0 {
      let coordinate2D: CLLocation = locations.first!
      let location = CLLocation(latitude: coordinate2D.coordinate.latitude, longitude: coordinate2D.coordinate.longitude)
      let printString = String(describing: location)
      self.LocationLabel.text = "Location: " + printString
      let geocoder: CLGeocoder = CLGeocoder()
      geocoder.reverseGeocodeLocation(location, completionHandler: {(placemarks, error) -> Void in
      if error != nil {
      let errorString = String(describing: error?.localizedDescription)
      print("reverse geodcode fail: (errorString)")
      self.LocationCounterLabel.text = ""
      self.RequestCounterLabel.text = ""
      self.LocationLabel.text = "Reverse Geodcode fail: (errorString)"
      self.PlacemarkLabel.text = ""
      self.requestingPlacemark = false
      return}
      else {
      let pm = placemarks! as [CLPlacemark]
      //There is ALWAYS 'placemarks' Data
      if pm.count > 0 {
      self.placemarkData = placemarks![0]
      self.printPlacemarkData = true
      self.printPlacemarks()
      self.requestingPlacemark = false}}})}
      else {
      if self.requestingPlacemark {
      self.LocationLabel.text = "Problem: There is no 'location.first'"}}}}}}


      And then the Storyboard UI:



      Storyboard Image



      View Controller Image



      <?xml version="1.0" encoding="UTF-8"?>
      <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
      <device id="retina4_7" orientation="portrait">
      <adaptation id="fullscreen"/>
      </device>
      <dependencies>
      <deployment identifier="iOS"/>
      <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14460.20"/>
      <capability name="Safe area layout guides" minToolsVersion="9.0"/>
      <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
      </dependencies>
      <scenes>
      <!--View Controller-->
      <scene sceneID="tne-QT-ifu">
      <objects>
      <viewController id="BYZ-38-t0r" customClass="ViewController" customModule="MyThoroughfare" customModuleProvider="target" sceneMemberID="viewController">
      <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
      <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
      <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
      <subviews>
      <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Location Counter" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ZIg-u9-TMR">
      <rect key="frame" x="16" y="20" width="343" height="20.5"/>
      <color key="backgroundColor" red="0.80000001190000003" green="0.80000001190000003" blue="0.80000001190000003" alpha="1" colorSpace="calibratedRGB"/>
      <fontDescription key="fontDescription" type="system" pointSize="17"/>
      <nil key="textColor"/>
      <nil key="highlightedColor"/>
      </label>
      <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Location Count Label" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="csF-KS-xGE">
      <rect key="frame" x="16" y="48" width="343" height="20.5"/>
      <color key="backgroundColor" red="0.80000001190000003" green="0.80000001190000003" blue="0.80000001190000003" alpha="1" colorSpace="calibratedRGB"/>
      <fontDescription key="fontDescription" type="system" pointSize="17"/>
      <nil key="textColor"/>
      <nil key="highlightedColor"/>
      </label>
      <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Location String" lineBreakMode="tailTruncation" numberOfLines="8" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="qOc-gk-gSp">
      <rect key="frame" x="16" y="76" width="343" height="20.5"/>
      <color key="backgroundColor" red="0.80000001190000003" green="0.80000001190000003" blue="0.80000001190000003" alpha="1" colorSpace="calibratedRGB"/>
      <fontDescription key="fontDescription" type="system" pointSize="17"/>
      <nil key="textColor"/>
      <nil key="highlightedColor"/>
      </label>
      <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Placemark String" lineBreakMode="tailTruncation" numberOfLines="14" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="42A-nO-tNf">
      <rect key="frame" x="16" y="104" width="343" height="20.5"/>
      <color key="backgroundColor" red="0.80000001190000003" green="0.80000001190000003" blue="0.80000001190000003" alpha="1" colorSpace="calibratedRGB"/>
      <fontDescription key="fontDescription" type="system" pointSize="17"/>
      <nil key="textColor"/>
      <nil key="highlightedColor"/>
      </label>
      <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="HgN-oB-ds0">
      <rect key="frame" x="121.5" y="578" width="132" height="30"/>
      <state key="normal" title="Request Placemark"/>
      <connections>
      <action selector="RefreshLocationButton:" destination="BYZ-38-t0r" eventType="touchUpInside" id="izY-S5-wjg"/>
      </connections>
      </button>
      </subviews>
      <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
      <constraints>
      <constraint firstItem="ZIg-u9-TMR" firstAttribute="leading" secondItem="6Tk-OE-BBY" secondAttribute="leading" constant="16" id="6HO-kN-l1z"/>
      <constraint firstItem="qOc-gk-gSp" firstAttribute="top" secondItem="csF-KS-xGE" secondAttribute="bottom" constant="7.5" id="6ux-dx-gJr"/>
      <constraint firstItem="6Tk-OE-BBY" firstAttribute="trailing" secondItem="42A-nO-tNf" secondAttribute="trailing" constant="16" id="8dG-gV-Cob"/>
      <constraint firstItem="HgN-oB-ds0" firstAttribute="centerX" secondItem="8bC-Xf-vdC" secondAttribute="centerX" id="A38-Nt-i3D"/>
      <constraint firstItem="6Tk-OE-BBY" firstAttribute="trailing" secondItem="ZIg-u9-TMR" secondAttribute="trailing" constant="16" id="Bb0-YC-oov"/>
      <constraint firstItem="csF-KS-xGE" firstAttribute="leading" secondItem="6Tk-OE-BBY" secondAttribute="leading" constant="16" id="FJU-ha-HkL"/>
      <constraint firstItem="42A-nO-tNf" firstAttribute="top" secondItem="qOc-gk-gSp" secondAttribute="bottom" constant="7.5" id="SpR-XB-MLG"/>
      <constraint firstItem="6Tk-OE-BBY" firstAttribute="bottom" secondItem="HgN-oB-ds0" secondAttribute="bottom" constant="59" id="Vr6-QE-230"/>
      <constraint firstItem="42A-nO-tNf" firstAttribute="leading" secondItem="6Tk-OE-BBY" secondAttribute="leading" constant="16" id="aHo-kJ-aCb"/>
      <constraint firstItem="csF-KS-xGE" firstAttribute="top" secondItem="ZIg-u9-TMR" secondAttribute="bottom" constant="7.5" id="c63-Mq-ItW"/>
      <constraint firstItem="6Tk-OE-BBY" firstAttribute="trailing" secondItem="csF-KS-xGE" secondAttribute="trailing" constant="16" id="dlV-Hc-8XJ"/>
      <constraint firstItem="qOc-gk-gSp" firstAttribute="leading" secondItem="6Tk-OE-BBY" secondAttribute="leading" constant="16" id="m5y-Q8-jxI"/>
      <constraint firstItem="ZIg-u9-TMR" firstAttribute="top" secondItem="6Tk-OE-BBY" secondAttribute="top" id="sdw-WQ-Bx9"/>
      <constraint firstItem="6Tk-OE-BBY" firstAttribute="trailing" secondItem="qOc-gk-gSp" secondAttribute="trailing" constant="16" id="woB-ig-i5v"/>
      </constraints>
      <viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
      </view>
      <connections>
      <outlet property="LocationCounterLabel" destination="ZIg-u9-TMR" id="K4g-WT-f82"/>
      <outlet property="LocationLabel" destination="qOc-gk-gSp" id="Cdw-bw-EWt"/>
      <outlet property="PlacemarkLabel" destination="42A-nO-tNf" id="dMh-bw-cRE"/>
      <outlet property="RequestCounterLabel" destination="csF-KS-xGE" id="ai6-zn-Toi"/>
      </connections>
      </viewController>
      <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
      </objects>
      <point key="canvasLocation" x="53.600000000000001" y="66.11694152923539"/>
      </scene>
      </scenes>
      </document>





      share|improve this answer




























        0












        0








        0







        There are so many questions dealing with 'reverseGeocodeLocation' on Stack Overflow, I've seen so many of them. I'm using Swift 4.2 and I thought my 'reverseGeocodeLocation' requests might be timing out. Well, this is NOT the case, when starting to move with an iPhone the 'didUpdateLocations' cycles need to mature. It can take two or more cycles before 'reverseGeocodeLocation' returns placemarks.



        I wrote a simple app that uses 'reverseGeocodeLocation' until 'placemarks' are returned after repeated 'didUpdateLocations' cycles. This is my own home grown 'SampleCode'. I learned a lot from using the app, it might help others understand how reverse geocode requests work in the real world.



        Please give your comments on possible improvements. This code is freely given and freely taken.



        import Foundation
        import UIKit
        import CoreLocation

        class ViewController: UIViewController, CLLocationManagerDelegate {
        @IBAction func RefreshLocationButton(_ sender: Any) {
        self.requestingPlacemark = true
        self.placemarkData = nil
        //^Make another Placemark Request
        self.requestCounter = 0
        self.RequestCounterLabel.text = ""
        self.LocationLabel.text = ""
        self.PlacemarkLabel.text = ""}
        @IBOutlet weak var LocationCounterLabel: UILabel!
        @IBOutlet weak var RequestCounterLabel: UILabel!
        @IBOutlet weak var LocationLabel: UILabel!
        @IBOutlet weak var PlacemarkLabel: UILabel!
        let locationManager = CLLocationManager()
        var placemarkData: CLPlacemark!
        var placemarkString: String!
        var printPlacemarkData: Bool!
        var didUpdateLocationsCounter: Int = 0
        var requestCounter: Int = 0
        var requestingPlacemark: Bool = true

        override func viewDidLoad() {
        super.viewDidLoad()
        if CLLocationManager.locationServicesEnabled() {
        locationManager.requestAlwaysAuthorization()
        locationManager.delegate = self
        //locationManager.desiredAccuracy = kCLLocationAccuracyBest
        locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation
        locationManager.startUpdatingLocation()
        self.RequestCounterLabel.text = ""
        self.LocationLabel.text = ""
        self.PlacemarkLabel.text = ""}}
        func printPlacemarks() {
        if printPlacemarkData {
        self.placemarkString = "Placemark Data:"
        self.placemarkString = buildPlacemarkString(item: 1)
        self.placemarkString = buildPlacemarkString(item: 2)
        self.placemarkString = buildPlacemarkString(item: 3)
        self.placemarkString = buildPlacemarkString(item: 4)
        self.placemarkString = buildPlacemarkString(item: 5)
        self.placemarkString = buildPlacemarkString(item: 6)
        self.placemarkString = buildPlacemarkString(item: 7)
        self.placemarkString = buildPlacemarkString(item: 8)
        self.placemarkString = buildPlacemarkString(item: 9)
        self.placemarkString = buildPlacemarkString(item: 10)
        self.PlacemarkLabel.text = self.placemarkString
        self.printPlacemarkData = false}}
        func buildPlacemarkString(item: Int) -> String {
        var elementText: String!
        var newString: String!
        switch item {
        case 1: elementText = "name: " + self.placemarkData.name!
        case 2: elementText = "subThoroughfare: " + self.placemarkData.subThoroughfare!
        case 3: elementText = "thoroughfare: " + self.placemarkData.thoroughfare!
        case 4: elementText = "postalCode: " + self.placemarkData.postalCode!
        case 5: elementText = "subLocality: " + self.placemarkData.subLocality!
        case 6: elementText = "locality: " + self.placemarkData.locality!
        case 7: elementText = "subAdministrativeArea: " + self.placemarkData.subAdministrativeArea!
        case 8: elementText = "administrativeArea: " + self.placemarkData.administrativeArea!
        case 9: elementText = "country: " + self.placemarkData.country!
        case 10: elementText = "isoCountryCode: " + self.placemarkData.isoCountryCode!
        default: print("Error: incorrect item number!")}
        newString = self.placemarkString + "n" + elementText
        return newString
        }
        func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        //location prints one time and 'didUpdateLocations' is stopped:
        self.didUpdateLocationsCounter = self.didUpdateLocationsCounter + 1
        let labelString = String(describing: self.didUpdateLocationsCounter)
        self.LocationCounterLabel.text = "Location Update Counter: " + labelString
        if self.placemarkData == nil {
        //location variable:
        self.requestCounter = self.requestCounter + 1
        let textString = String(describing: self.requestCounter)
        self.RequestCounterLabel.text = "Request Counter: " + textString
        if locations.count == 0 {
        self.LocationLabel.text = "Locations: There was NONE"}
        else {
        if locations.count > 0 {
        let coordinate2D: CLLocation = locations.first!
        let location = CLLocation(latitude: coordinate2D.coordinate.latitude, longitude: coordinate2D.coordinate.longitude)
        let printString = String(describing: location)
        self.LocationLabel.text = "Location: " + printString
        let geocoder: CLGeocoder = CLGeocoder()
        geocoder.reverseGeocodeLocation(location, completionHandler: {(placemarks, error) -> Void in
        if error != nil {
        let errorString = String(describing: error?.localizedDescription)
        print("reverse geodcode fail: (errorString)")
        self.LocationCounterLabel.text = ""
        self.RequestCounterLabel.text = ""
        self.LocationLabel.text = "Reverse Geodcode fail: (errorString)"
        self.PlacemarkLabel.text = ""
        self.requestingPlacemark = false
        return}
        else {
        let pm = placemarks! as [CLPlacemark]
        //There is ALWAYS 'placemarks' Data
        if pm.count > 0 {
        self.placemarkData = placemarks![0]
        self.printPlacemarkData = true
        self.printPlacemarks()
        self.requestingPlacemark = false}}})}
        else {
        if self.requestingPlacemark {
        self.LocationLabel.text = "Problem: There is no 'location.first'"}}}}}}


        And then the Storyboard UI:



        Storyboard Image



        View Controller Image



        <?xml version="1.0" encoding="UTF-8"?>
        <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
        <device id="retina4_7" orientation="portrait">
        <adaptation id="fullscreen"/>
        </device>
        <dependencies>
        <deployment identifier="iOS"/>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14460.20"/>
        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
        </dependencies>
        <scenes>
        <!--View Controller-->
        <scene sceneID="tne-QT-ifu">
        <objects>
        <viewController id="BYZ-38-t0r" customClass="ViewController" customModule="MyThoroughfare" customModuleProvider="target" sceneMemberID="viewController">
        <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
        <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
        <subviews>
        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Location Counter" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ZIg-u9-TMR">
        <rect key="frame" x="16" y="20" width="343" height="20.5"/>
        <color key="backgroundColor" red="0.80000001190000003" green="0.80000001190000003" blue="0.80000001190000003" alpha="1" colorSpace="calibratedRGB"/>
        <fontDescription key="fontDescription" type="system" pointSize="17"/>
        <nil key="textColor"/>
        <nil key="highlightedColor"/>
        </label>
        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Location Count Label" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="csF-KS-xGE">
        <rect key="frame" x="16" y="48" width="343" height="20.5"/>
        <color key="backgroundColor" red="0.80000001190000003" green="0.80000001190000003" blue="0.80000001190000003" alpha="1" colorSpace="calibratedRGB"/>
        <fontDescription key="fontDescription" type="system" pointSize="17"/>
        <nil key="textColor"/>
        <nil key="highlightedColor"/>
        </label>
        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Location String" lineBreakMode="tailTruncation" numberOfLines="8" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="qOc-gk-gSp">
        <rect key="frame" x="16" y="76" width="343" height="20.5"/>
        <color key="backgroundColor" red="0.80000001190000003" green="0.80000001190000003" blue="0.80000001190000003" alpha="1" colorSpace="calibratedRGB"/>
        <fontDescription key="fontDescription" type="system" pointSize="17"/>
        <nil key="textColor"/>
        <nil key="highlightedColor"/>
        </label>
        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Placemark String" lineBreakMode="tailTruncation" numberOfLines="14" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="42A-nO-tNf">
        <rect key="frame" x="16" y="104" width="343" height="20.5"/>
        <color key="backgroundColor" red="0.80000001190000003" green="0.80000001190000003" blue="0.80000001190000003" alpha="1" colorSpace="calibratedRGB"/>
        <fontDescription key="fontDescription" type="system" pointSize="17"/>
        <nil key="textColor"/>
        <nil key="highlightedColor"/>
        </label>
        <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="HgN-oB-ds0">
        <rect key="frame" x="121.5" y="578" width="132" height="30"/>
        <state key="normal" title="Request Placemark"/>
        <connections>
        <action selector="RefreshLocationButton:" destination="BYZ-38-t0r" eventType="touchUpInside" id="izY-S5-wjg"/>
        </connections>
        </button>
        </subviews>
        <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
        <constraints>
        <constraint firstItem="ZIg-u9-TMR" firstAttribute="leading" secondItem="6Tk-OE-BBY" secondAttribute="leading" constant="16" id="6HO-kN-l1z"/>
        <constraint firstItem="qOc-gk-gSp" firstAttribute="top" secondItem="csF-KS-xGE" secondAttribute="bottom" constant="7.5" id="6ux-dx-gJr"/>
        <constraint firstItem="6Tk-OE-BBY" firstAttribute="trailing" secondItem="42A-nO-tNf" secondAttribute="trailing" constant="16" id="8dG-gV-Cob"/>
        <constraint firstItem="HgN-oB-ds0" firstAttribute="centerX" secondItem="8bC-Xf-vdC" secondAttribute="centerX" id="A38-Nt-i3D"/>
        <constraint firstItem="6Tk-OE-BBY" firstAttribute="trailing" secondItem="ZIg-u9-TMR" secondAttribute="trailing" constant="16" id="Bb0-YC-oov"/>
        <constraint firstItem="csF-KS-xGE" firstAttribute="leading" secondItem="6Tk-OE-BBY" secondAttribute="leading" constant="16" id="FJU-ha-HkL"/>
        <constraint firstItem="42A-nO-tNf" firstAttribute="top" secondItem="qOc-gk-gSp" secondAttribute="bottom" constant="7.5" id="SpR-XB-MLG"/>
        <constraint firstItem="6Tk-OE-BBY" firstAttribute="bottom" secondItem="HgN-oB-ds0" secondAttribute="bottom" constant="59" id="Vr6-QE-230"/>
        <constraint firstItem="42A-nO-tNf" firstAttribute="leading" secondItem="6Tk-OE-BBY" secondAttribute="leading" constant="16" id="aHo-kJ-aCb"/>
        <constraint firstItem="csF-KS-xGE" firstAttribute="top" secondItem="ZIg-u9-TMR" secondAttribute="bottom" constant="7.5" id="c63-Mq-ItW"/>
        <constraint firstItem="6Tk-OE-BBY" firstAttribute="trailing" secondItem="csF-KS-xGE" secondAttribute="trailing" constant="16" id="dlV-Hc-8XJ"/>
        <constraint firstItem="qOc-gk-gSp" firstAttribute="leading" secondItem="6Tk-OE-BBY" secondAttribute="leading" constant="16" id="m5y-Q8-jxI"/>
        <constraint firstItem="ZIg-u9-TMR" firstAttribute="top" secondItem="6Tk-OE-BBY" secondAttribute="top" id="sdw-WQ-Bx9"/>
        <constraint firstItem="6Tk-OE-BBY" firstAttribute="trailing" secondItem="qOc-gk-gSp" secondAttribute="trailing" constant="16" id="woB-ig-i5v"/>
        </constraints>
        <viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
        </view>
        <connections>
        <outlet property="LocationCounterLabel" destination="ZIg-u9-TMR" id="K4g-WT-f82"/>
        <outlet property="LocationLabel" destination="qOc-gk-gSp" id="Cdw-bw-EWt"/>
        <outlet property="PlacemarkLabel" destination="42A-nO-tNf" id="dMh-bw-cRE"/>
        <outlet property="RequestCounterLabel" destination="csF-KS-xGE" id="ai6-zn-Toi"/>
        </connections>
        </viewController>
        <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
        </objects>
        <point key="canvasLocation" x="53.600000000000001" y="66.11694152923539"/>
        </scene>
        </scenes>
        </document>





        share|improve this answer















        There are so many questions dealing with 'reverseGeocodeLocation' on Stack Overflow, I've seen so many of them. I'm using Swift 4.2 and I thought my 'reverseGeocodeLocation' requests might be timing out. Well, this is NOT the case, when starting to move with an iPhone the 'didUpdateLocations' cycles need to mature. It can take two or more cycles before 'reverseGeocodeLocation' returns placemarks.



        I wrote a simple app that uses 'reverseGeocodeLocation' until 'placemarks' are returned after repeated 'didUpdateLocations' cycles. This is my own home grown 'SampleCode'. I learned a lot from using the app, it might help others understand how reverse geocode requests work in the real world.



        Please give your comments on possible improvements. This code is freely given and freely taken.



        import Foundation
        import UIKit
        import CoreLocation

        class ViewController: UIViewController, CLLocationManagerDelegate {
        @IBAction func RefreshLocationButton(_ sender: Any) {
        self.requestingPlacemark = true
        self.placemarkData = nil
        //^Make another Placemark Request
        self.requestCounter = 0
        self.RequestCounterLabel.text = ""
        self.LocationLabel.text = ""
        self.PlacemarkLabel.text = ""}
        @IBOutlet weak var LocationCounterLabel: UILabel!
        @IBOutlet weak var RequestCounterLabel: UILabel!
        @IBOutlet weak var LocationLabel: UILabel!
        @IBOutlet weak var PlacemarkLabel: UILabel!
        let locationManager = CLLocationManager()
        var placemarkData: CLPlacemark!
        var placemarkString: String!
        var printPlacemarkData: Bool!
        var didUpdateLocationsCounter: Int = 0
        var requestCounter: Int = 0
        var requestingPlacemark: Bool = true

        override func viewDidLoad() {
        super.viewDidLoad()
        if CLLocationManager.locationServicesEnabled() {
        locationManager.requestAlwaysAuthorization()
        locationManager.delegate = self
        //locationManager.desiredAccuracy = kCLLocationAccuracyBest
        locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation
        locationManager.startUpdatingLocation()
        self.RequestCounterLabel.text = ""
        self.LocationLabel.text = ""
        self.PlacemarkLabel.text = ""}}
        func printPlacemarks() {
        if printPlacemarkData {
        self.placemarkString = "Placemark Data:"
        self.placemarkString = buildPlacemarkString(item: 1)
        self.placemarkString = buildPlacemarkString(item: 2)
        self.placemarkString = buildPlacemarkString(item: 3)
        self.placemarkString = buildPlacemarkString(item: 4)
        self.placemarkString = buildPlacemarkString(item: 5)
        self.placemarkString = buildPlacemarkString(item: 6)
        self.placemarkString = buildPlacemarkString(item: 7)
        self.placemarkString = buildPlacemarkString(item: 8)
        self.placemarkString = buildPlacemarkString(item: 9)
        self.placemarkString = buildPlacemarkString(item: 10)
        self.PlacemarkLabel.text = self.placemarkString
        self.printPlacemarkData = false}}
        func buildPlacemarkString(item: Int) -> String {
        var elementText: String!
        var newString: String!
        switch item {
        case 1: elementText = "name: " + self.placemarkData.name!
        case 2: elementText = "subThoroughfare: " + self.placemarkData.subThoroughfare!
        case 3: elementText = "thoroughfare: " + self.placemarkData.thoroughfare!
        case 4: elementText = "postalCode: " + self.placemarkData.postalCode!
        case 5: elementText = "subLocality: " + self.placemarkData.subLocality!
        case 6: elementText = "locality: " + self.placemarkData.locality!
        case 7: elementText = "subAdministrativeArea: " + self.placemarkData.subAdministrativeArea!
        case 8: elementText = "administrativeArea: " + self.placemarkData.administrativeArea!
        case 9: elementText = "country: " + self.placemarkData.country!
        case 10: elementText = "isoCountryCode: " + self.placemarkData.isoCountryCode!
        default: print("Error: incorrect item number!")}
        newString = self.placemarkString + "n" + elementText
        return newString
        }
        func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        //location prints one time and 'didUpdateLocations' is stopped:
        self.didUpdateLocationsCounter = self.didUpdateLocationsCounter + 1
        let labelString = String(describing: self.didUpdateLocationsCounter)
        self.LocationCounterLabel.text = "Location Update Counter: " + labelString
        if self.placemarkData == nil {
        //location variable:
        self.requestCounter = self.requestCounter + 1
        let textString = String(describing: self.requestCounter)
        self.RequestCounterLabel.text = "Request Counter: " + textString
        if locations.count == 0 {
        self.LocationLabel.text = "Locations: There was NONE"}
        else {
        if locations.count > 0 {
        let coordinate2D: CLLocation = locations.first!
        let location = CLLocation(latitude: coordinate2D.coordinate.latitude, longitude: coordinate2D.coordinate.longitude)
        let printString = String(describing: location)
        self.LocationLabel.text = "Location: " + printString
        let geocoder: CLGeocoder = CLGeocoder()
        geocoder.reverseGeocodeLocation(location, completionHandler: {(placemarks, error) -> Void in
        if error != nil {
        let errorString = String(describing: error?.localizedDescription)
        print("reverse geodcode fail: (errorString)")
        self.LocationCounterLabel.text = ""
        self.RequestCounterLabel.text = ""
        self.LocationLabel.text = "Reverse Geodcode fail: (errorString)"
        self.PlacemarkLabel.text = ""
        self.requestingPlacemark = false
        return}
        else {
        let pm = placemarks! as [CLPlacemark]
        //There is ALWAYS 'placemarks' Data
        if pm.count > 0 {
        self.placemarkData = placemarks![0]
        self.printPlacemarkData = true
        self.printPlacemarks()
        self.requestingPlacemark = false}}})}
        else {
        if self.requestingPlacemark {
        self.LocationLabel.text = "Problem: There is no 'location.first'"}}}}}}


        And then the Storyboard UI:



        Storyboard Image



        View Controller Image



        <?xml version="1.0" encoding="UTF-8"?>
        <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
        <device id="retina4_7" orientation="portrait">
        <adaptation id="fullscreen"/>
        </device>
        <dependencies>
        <deployment identifier="iOS"/>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14460.20"/>
        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
        </dependencies>
        <scenes>
        <!--View Controller-->
        <scene sceneID="tne-QT-ifu">
        <objects>
        <viewController id="BYZ-38-t0r" customClass="ViewController" customModule="MyThoroughfare" customModuleProvider="target" sceneMemberID="viewController">
        <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
        <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
        <subviews>
        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Location Counter" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ZIg-u9-TMR">
        <rect key="frame" x="16" y="20" width="343" height="20.5"/>
        <color key="backgroundColor" red="0.80000001190000003" green="0.80000001190000003" blue="0.80000001190000003" alpha="1" colorSpace="calibratedRGB"/>
        <fontDescription key="fontDescription" type="system" pointSize="17"/>
        <nil key="textColor"/>
        <nil key="highlightedColor"/>
        </label>
        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Location Count Label" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="csF-KS-xGE">
        <rect key="frame" x="16" y="48" width="343" height="20.5"/>
        <color key="backgroundColor" red="0.80000001190000003" green="0.80000001190000003" blue="0.80000001190000003" alpha="1" colorSpace="calibratedRGB"/>
        <fontDescription key="fontDescription" type="system" pointSize="17"/>
        <nil key="textColor"/>
        <nil key="highlightedColor"/>
        </label>
        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Location String" lineBreakMode="tailTruncation" numberOfLines="8" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="qOc-gk-gSp">
        <rect key="frame" x="16" y="76" width="343" height="20.5"/>
        <color key="backgroundColor" red="0.80000001190000003" green="0.80000001190000003" blue="0.80000001190000003" alpha="1" colorSpace="calibratedRGB"/>
        <fontDescription key="fontDescription" type="system" pointSize="17"/>
        <nil key="textColor"/>
        <nil key="highlightedColor"/>
        </label>
        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Placemark String" lineBreakMode="tailTruncation" numberOfLines="14" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="42A-nO-tNf">
        <rect key="frame" x="16" y="104" width="343" height="20.5"/>
        <color key="backgroundColor" red="0.80000001190000003" green="0.80000001190000003" blue="0.80000001190000003" alpha="1" colorSpace="calibratedRGB"/>
        <fontDescription key="fontDescription" type="system" pointSize="17"/>
        <nil key="textColor"/>
        <nil key="highlightedColor"/>
        </label>
        <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="HgN-oB-ds0">
        <rect key="frame" x="121.5" y="578" width="132" height="30"/>
        <state key="normal" title="Request Placemark"/>
        <connections>
        <action selector="RefreshLocationButton:" destination="BYZ-38-t0r" eventType="touchUpInside" id="izY-S5-wjg"/>
        </connections>
        </button>
        </subviews>
        <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
        <constraints>
        <constraint firstItem="ZIg-u9-TMR" firstAttribute="leading" secondItem="6Tk-OE-BBY" secondAttribute="leading" constant="16" id="6HO-kN-l1z"/>
        <constraint firstItem="qOc-gk-gSp" firstAttribute="top" secondItem="csF-KS-xGE" secondAttribute="bottom" constant="7.5" id="6ux-dx-gJr"/>
        <constraint firstItem="6Tk-OE-BBY" firstAttribute="trailing" secondItem="42A-nO-tNf" secondAttribute="trailing" constant="16" id="8dG-gV-Cob"/>
        <constraint firstItem="HgN-oB-ds0" firstAttribute="centerX" secondItem="8bC-Xf-vdC" secondAttribute="centerX" id="A38-Nt-i3D"/>
        <constraint firstItem="6Tk-OE-BBY" firstAttribute="trailing" secondItem="ZIg-u9-TMR" secondAttribute="trailing" constant="16" id="Bb0-YC-oov"/>
        <constraint firstItem="csF-KS-xGE" firstAttribute="leading" secondItem="6Tk-OE-BBY" secondAttribute="leading" constant="16" id="FJU-ha-HkL"/>
        <constraint firstItem="42A-nO-tNf" firstAttribute="top" secondItem="qOc-gk-gSp" secondAttribute="bottom" constant="7.5" id="SpR-XB-MLG"/>
        <constraint firstItem="6Tk-OE-BBY" firstAttribute="bottom" secondItem="HgN-oB-ds0" secondAttribute="bottom" constant="59" id="Vr6-QE-230"/>
        <constraint firstItem="42A-nO-tNf" firstAttribute="leading" secondItem="6Tk-OE-BBY" secondAttribute="leading" constant="16" id="aHo-kJ-aCb"/>
        <constraint firstItem="csF-KS-xGE" firstAttribute="top" secondItem="ZIg-u9-TMR" secondAttribute="bottom" constant="7.5" id="c63-Mq-ItW"/>
        <constraint firstItem="6Tk-OE-BBY" firstAttribute="trailing" secondItem="csF-KS-xGE" secondAttribute="trailing" constant="16" id="dlV-Hc-8XJ"/>
        <constraint firstItem="qOc-gk-gSp" firstAttribute="leading" secondItem="6Tk-OE-BBY" secondAttribute="leading" constant="16" id="m5y-Q8-jxI"/>
        <constraint firstItem="ZIg-u9-TMR" firstAttribute="top" secondItem="6Tk-OE-BBY" secondAttribute="top" id="sdw-WQ-Bx9"/>
        <constraint firstItem="6Tk-OE-BBY" firstAttribute="trailing" secondItem="qOc-gk-gSp" secondAttribute="trailing" constant="16" id="woB-ig-i5v"/>
        </constraints>
        <viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
        </view>
        <connections>
        <outlet property="LocationCounterLabel" destination="ZIg-u9-TMR" id="K4g-WT-f82"/>
        <outlet property="LocationLabel" destination="qOc-gk-gSp" id="Cdw-bw-EWt"/>
        <outlet property="PlacemarkLabel" destination="42A-nO-tNf" id="dMh-bw-cRE"/>
        <outlet property="RequestCounterLabel" destination="csF-KS-xGE" id="ai6-zn-Toi"/>
        </connections>
        </viewController>
        <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
        </objects>
        <point key="canvasLocation" x="53.600000000000001" y="66.11694152923539"/>
        </scene>
        </scenes>
        </document>






        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Jan 1 at 5:25

























        answered Jan 1 at 0:40









        B. WasonB. Wason

        145




        145






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f46869394%2freverse-geocoding-in-swift-4%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            MongoDB - Not Authorized To Execute Command

            How to fix TextFormField cause rebuild widget in Flutter

            in spring boot 2.1 many test slices are not allowed anymore due to multiple @BootstrapWith