iosswiftcllocationregionclplacemark

How to get USA Region and Division of current CLLocation or CLPlacemark?


I have this struct called Address where I would pass down a CLPlacemark as a parameter. The problem here is I couldn't get the Region or Division from existing iOS frameworks and classes.

struct Address: Codable {

    var street: String?
    var city: String?
    var state: String?
    var zip_code: String?
    var formatted_address: String?
    var latitude: Double?
    var longitude: Double?
    var region: String?
    var division: String?

    init?(placemark: CLPlacemark) {
        var address = ""

        if let address1 = placemark.thoroughfare {
            self.street = address1
            address += " \(address1),"
        }

        if let address2 = placemark.subThoroughfare {
            address += " \(address2),"
            self.street = address2
        }

        if let city = placemark.locality {
            address += " \(city),"
            self.city = city
        }

        if let state = placemark.administrativeArea {
            address += " \(state),"
            self.state = state
        }

        if let zip = placemark.postalCode {
            address += " \(zip)"
            self.zip_code = zip
        }

        if let location = placemark.location {
            let coordinates = location.coordinate
            self.latitude = coordinates.latitude
            self.longitude = coordinates.longitude
        }

        self.formatted_address = address

    }

    var coordinates: CLLocationCoordinate2D? {
        if let latitude = self.latitude, let longitude = self.longitude {
            return CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
        }

        return nil
    }
}

How could I achieve this? I'm thinking one way is to just list down the regions and divisions using a dictionary, with the array of state and if the dictionary which holds an array contains the state then it is the region/division. Is there any better solution?


Solution

  • The only solution I got for this was just to declare two static arrays of String: [String] dictionary. One is an array of regions and another is an array of divisions.

    It looks something like below:

    let regions: [String: [String]] = [
        "Northeast": [
            "New England", "Middle Atlantic"
        ],
        "Midwest": [
            "East North Central", "West North Central"
        ],
        "South": [
            "South Atlantic", "East South Central", "West South Central"
        ],
        "West": [
            "Mountain", "Pacific"
        ],
    ]
    
    let divisions: [String: [String]] = [
        "New England": [
            "CT", "MA", "ME", "NH", "RI", "VT"
        ],
        "Middle Atlantic": [
            "NJ", "NY", "PA"
        ],
        "East North Central": [
            "IL", "IN", "MI", "OH", "WI"
        ],
        "West North Central": [
            "IA", "KS", "MN", "MO", "ND", "NE", "SD"
        ],
        "South Atlantic": [
            "DC", "DE", "FL", "GA", "MD", "NC", "SC", "VA", "WV"
        ],
        "East South Central": [
            "AL", "KY", "MS", "TN"
        ],
        "West South Central": [
            "AR", "LA", "OK", "TX"
        ],
        "Mountain": [
            "AZ", "CO", "ID", "MT", "NM", "NV", "UT", "WA"
        ],
        "Pacific": [
            "AK", "CA", "HI", "OR", "WA"
        ]
    ]
    

    Then to get the right value out of the division and region. I would use the state that I get from the placemark.

    if let state = placemark.administrativeArea {
                address += " \(state),"
                self.state = state
                self.division = self.divisions.filter({ $0.value.contains(state) }).first?.key
                if let division = self.division {
                    self.region = self.regions.filter({ $0.value.contains(division) }).first?.key
                }
            }
    

    I couldn't find a better solution as of the moment, but if you guys have any suggestions I would gladly want to know.