Skip to content

Commit

Permalink
Refactor code
Browse files Browse the repository at this point in the history
  • Loading branch information
lminhtm committed Apr 29, 2019
1 parent fb0592f commit 8188b9f
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 76 deletions.
32 changes: 16 additions & 16 deletions Example/LMGeocoderSwift/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class ViewController: UIViewController, CLLocationManagerDelegate {
super.viewDidLoad()

// You can set your google API key here
LMGeocoder.sharedInstance.googleAPIKey = ""
LMGeocoder.shared.googleAPIKey = ""

// Start getting current location
self.locationManager.delegate = self
Expand Down Expand Up @@ -89,21 +89,21 @@ class ViewController: UIViewController, CLLocationManagerDelegate {
self.longitudeLabel.text = String(format: "%f", coordinate.longitude)

// Start to reverse geocode
LMGeocoder.sharedInstance.cancelGeocode()
LMGeocoder.sharedInstance.reverseGeocode(coordinate: coordinate,
service: .AppleService,
completionHandler: { (results: Array<LMAddress>?, error: Error?) in
// Parse formatted address
var formattedAddress: String? = "-"
if let address = results?.first, error == nil {
formattedAddress = address.formattedAddress
}
// Update UI
DispatchQueue.main.async {
self.addressLabel.text = formattedAddress
}
LMGeocoder.shared.cancelGeocode()
LMGeocoder.shared.reverseGeocode(coordinate: coordinate,
service: .GoogleService,
completionHandler: { (results: Array<LMAddress>?, error: Error?) in

// Parse formatted address
var formattedAddress: String? = "-"
if let address = results?.first, error == nil {
formattedAddress = address.formattedAddress
}

// Update UI
DispatchQueue.main.async {
self.addressLabel.text = formattedAddress
}
})
}
}
Expand Down
50 changes: 25 additions & 25 deletions LMGeocoderSwift/Classes/LMAddress.swift
Original file line number Diff line number Diff line change
Expand Up @@ -80,21 +80,21 @@ public struct LMAddress {

guard let placemark = locationData as? CLPlacemark else { return }

self.coordinate = placemark.location?.coordinate
self.streetNumber = placemark.thoroughfare
self.locality = placemark.locality
self.subLocality = placemark.subLocality
self.administrativeArea = placemark.administrativeArea
self.subAdministrativeArea = placemark.subAdministrativeArea
self.postalCode = placemark.postalCode
self.country = placemark.country
self.ISOcountryCode = placemark.isoCountryCode
coordinate = placemark.location?.coordinate
streetNumber = placemark.thoroughfare
locality = placemark.locality
subLocality = placemark.subLocality
administrativeArea = placemark.administrativeArea
subAdministrativeArea = placemark.subAdministrativeArea
postalCode = placemark.postalCode
country = placemark.country
ISOcountryCode = placemark.isoCountryCode
if #available(iOS 11.0, *) {
if let postalAddress = placemark.postalAddress {
self.formattedAddress = CNPostalAddressFormatter.string(from: postalAddress, style: .mailingAddress)
formattedAddress = CNPostalAddressFormatter.string(from: postalAddress, style: .mailingAddress)
}
}
self.rawSource = placemark
rawSource = placemark
}

private mutating func parseGoogleResponse(locationData: AnyObject) {
Expand All @@ -117,23 +117,23 @@ public struct LMAddress {
}
}

self.coordinate = CLLocationCoordinate2DMake(lat, lng)
self.streetNumber = self.getComponent(component: "street_number", array: addressComponents, type: "long_name")
self.route = self.getComponent(component: "route", array: addressComponents, type: "long_name")
self.locality = self.getComponent(component: "locality", array: addressComponents, type: "long_name")
self.subLocality = self.getComponent(component: "sublocality", array: addressComponents, type: "long_name")
self.administrativeArea = self.getComponent(component: "administrative_area_level_1", array: addressComponents, type: "long_name")
self.subAdministrativeArea = self.getComponent(component: "administrative_area_level_2", array: addressComponents, type: "long_name")
self.neighborhood = self.getComponent(component: "neighborhood", array: addressComponents, type: "long_name")
self.postalCode = self.getComponent(component: "postal_code", array: addressComponents, type: "short_name")
self.country = self.getComponent(component: "country", array: addressComponents, type: "long_name")
self.ISOcountryCode = self.getComponent(component: "country", array: addressComponents, type: "short_name")
coordinate = CLLocationCoordinate2DMake(lat, lng)
streetNumber = getComponent("street_number", inArray: addressComponents, ofType: "long_name")
route = getComponent("route", inArray: addressComponents, ofType: "long_name")
locality = getComponent("locality", inArray: addressComponents, ofType: "long_name")
subLocality = getComponent("sublocality", inArray: addressComponents, ofType: "long_name")
administrativeArea = getComponent("administrative_area_level_1", inArray: addressComponents, ofType: "long_name")
subAdministrativeArea = getComponent("administrative_area_level_2", inArray: addressComponents, ofType: "long_name")
neighborhood = getComponent("neighborhood", inArray: addressComponents, ofType: "long_name")
postalCode = getComponent("postal_code", inArray: addressComponents, ofType: "short_name")
country = getComponent("country", inArray: addressComponents, ofType: "long_name")
ISOcountryCode = getComponent("country", inArray: addressComponents, ofType: "short_name")
self.formattedAddress = formattedAddress
self.lines = formattedAddress?.components(separatedBy: ", ")
self.rawSource = locationData
lines = formattedAddress?.components(separatedBy: ", ")
rawSource = locationData
}

private func getComponent(component: String, array: Any?, type: String) -> String? {
private func getComponent(_ component: String, inArray array: Any?, ofType type: String) -> String? {

guard let array = array as? NSArray else { return nil }

Expand Down
65 changes: 31 additions & 34 deletions LMGeocoderSwift/Classes/LMGeocoder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@
import UIKit
import CoreLocation

/// LMGeocoder error codes, embedded in NSError.
public enum LMGeocoderErrorCode: Int {
case InvalidCoordinate = 1, InvalidAddressString, Internal
/// LMGeocoder error codes.
public enum LMGeocoderError: Error {
case InvalidCoordinate
case InvalidAddressString
case Internal
}

/// LMGeocoder service API.
Expand All @@ -20,6 +22,9 @@ public enum LMGeocoderService {
case AppleService
}

/// Google Geocoding API const
private let googleGeocodingURLString = "https://maps.googleapis.com/maps/api/geocode/json?sensor=true"

/// Handler that reports a geocoding response, or error.
public typealias LMGeocodeCallback = (_ results: Array<LMAddress>?, _ error: Error?) -> Void

Expand All @@ -42,7 +47,7 @@ open class LMGeocoder {

// MARK: SINGLETON

public static let sharedInstance = LMGeocoder()
public static let shared = LMGeocoder()

// MARK: PUBLIC

Expand All @@ -58,18 +63,14 @@ open class LMGeocoder {
/// - completionHandler: The callback to invoke with the geocode results. The callback will be invoked asynchronously from the main thread.
open func geocode(address: String, service: LMGeocoderService, completionHandler: LMGeocodeCallback?) {

self.isGeocoding = true
isGeocoding = true

// Check adress string
guard address.count != 0 else {

let error = NSError(domain: "LMGeocoderError",
code: LMGeocoderErrorCode.InvalidAddressString.rawValue,
userInfo: nil)

self.isGeocoding = false
isGeocoding = false
if let completionHandler = completionHandler {
completionHandler(nil, error)
completionHandler(nil, LMGeocoderError.InvalidAddressString)
}
return
}
Expand All @@ -78,11 +79,11 @@ open class LMGeocoder {
if service == .GoogleService
{
// Geocode using Google service
var urlString = "https://maps.googleapis.com/maps/api/geocode/json?sensor=true&address=\(address)"
if let key = self.googleAPIKey {
var urlString = googleGeocodingURLString + "&address=\(address)"
if let key = googleAPIKey {
urlString = urlString + "&key=" + key
}
self.buildAsynchronousRequest(urlString: urlString) { (results, error) in
buildAsynchronousRequest(urlString: urlString) { (results, error) in

self.isGeocoding = false
if let completionHandler = completionHandler {
Expand All @@ -93,9 +94,9 @@ open class LMGeocoder {
else if service == .AppleService
{
// Geocode using Apple service
self.appleGeocoder.geocodeAddressString(address) { (placemarks, error) in
appleGeocoder.geocodeAddressString(address) { (placemarks, error) in

let results = self.parseGeocodingResponse(results: placemarks, service: .AppleService)
let results = self.parseGeocodingResponse(placemarks, service: .AppleService)

self.isGeocoding = false
if let completionHandler = completionHandler {
Expand All @@ -117,18 +118,14 @@ open class LMGeocoder {
/// - completionHandler: The callback to invoke with the reverse geocode results.The callback will be invoked asynchronously from the main thread.
open func reverseGeocode(coordinate: CLLocationCoordinate2D, service: LMGeocoderService, completionHandler: LMGeocodeCallback?) {

self.isGeocoding = true
isGeocoding = true

// Check location coordinate
guard CLLocationCoordinate2DIsValid(coordinate) else {

let error = NSError(domain: "LMGeocoderError",
code: LMGeocoderErrorCode.InvalidCoordinate.rawValue,
userInfo: nil)

self.isGeocoding = false
isGeocoding = false
if let completionHandler = completionHandler {
completionHandler(nil, error)
completionHandler(nil, LMGeocoderError.InvalidCoordinate)
}
return
}
Expand All @@ -137,11 +134,11 @@ open class LMGeocoder {
if service == .GoogleService
{
// Reverse geocode using Google service
var urlString = "https://maps.googleapis.com/maps/api/geocode/json?sensor=true&latlng=\(coordinate.latitude),\(coordinate.longitude)"
if let key = self.googleAPIKey {
var urlString = googleGeocodingURLString + "&latlng=\(coordinate.latitude),\(coordinate.longitude)"
if let key = googleAPIKey {
urlString = urlString + "&key=" + key
}
self.buildAsynchronousRequest(urlString: urlString) { (results, error) in
buildAsynchronousRequest(urlString: urlString) { (results, error) in

self.isGeocoding = false
if let completionHandler = completionHandler {
Expand All @@ -153,9 +150,9 @@ open class LMGeocoder {
{
// Reverse geocode using Apple service
let location = CLLocation(latitude: coordinate.latitude, longitude: coordinate.longitude)
self.appleGeocoder.reverseGeocodeLocation(location) { (placemarks, error) in
appleGeocoder.reverseGeocodeLocation(location) { (placemarks, error) in

let results = self.parseGeocodingResponse(results: placemarks, service: .AppleService)
let results = self.parseGeocodingResponse(placemarks, service: .AppleService)

self.isGeocoding = false
if let completionHandler = completionHandler {
Expand All @@ -167,8 +164,8 @@ open class LMGeocoder {

/// Cancels a pending geocoding request.
open func cancelGeocode() {
self.appleGeocoder.cancelGeocode()
self.googleGeocoderTask?.cancel()
appleGeocoder.cancelGeocode()
googleGeocoderTask?.cancel()
}

// MARK: INTERNAL
Expand All @@ -179,7 +176,7 @@ open class LMGeocoder {
let urlString = urlString.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)!
let url = URL(string: urlString)!

self.googleGeocoderTask = URLSession.shared.dataTask(with: url, completionHandler: { (data, response, error) in
googleGeocoderTask = URLSession.shared.dataTask(with: url, completionHandler: { (data, response, error) in

if let data = data, error == nil {

Expand All @@ -190,7 +187,7 @@ open class LMGeocoder {
if let status = result["status"] as? String, status == "OK" {
// Status OK --> Parse response results
let locationDicts = result["results"] as? Array<AnyObject>
let finalResults = self.parseGeocodingResponse(results: locationDicts, service: .GoogleService)
let finalResults = self.parseGeocodingResponse(locationDicts, service: .GoogleService)
if let completionHandler = completionHandler {
completionHandler(finalResults, nil)
}
Expand All @@ -216,11 +213,11 @@ open class LMGeocoder {
}
}
})
self.googleGeocoderTask?.resume()
googleGeocoderTask?.resume()
}

/// Parse geocoding response
func parseGeocodingResponse(results: Array<AnyObject>?, service: LMGeocoderService) -> Array<LMAddress>? {
func parseGeocodingResponse(_ results: Array<AnyObject>?, service: LMGeocoderService) -> Array<LMAddress>? {

guard let results = results else { return nil }

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ LMGeocoderSwift is a simple wrapper for geocoding and reverse geocoding, using b

## Requirements
* iOS 8.0 or higher
* Swift 4.2
* Swift 5.0

## Installation
LMGeocoderSwift is available through [CocoaPods](https://cocoapods.org). To install
Expand Down

0 comments on commit 8188b9f

Please sign in to comment.