user3546854
user3546854

Reputation: 349

google maps get street number in swift

how to get street number from google map in swift?

my code:

let geocoder = GMSGeocoder()

geocoder.reverseGeocodeCoordinate(place.coordinate) { response, error in

   if let address = response?.firstResult() {
      print(address)
   }
})

and i get this:

GMSAddress {
coordinate: (56.966157, 24.054405)
lines: Buļļu iela 21, Kurzeme District, Rīga, LV-1055, Latvia
thoroughfare: 21 Buļļu iela
locality: Rīga
administrativeArea: Rīgas pilsēta
postalCode: LV-1055
country: Latvia
}

So... how to get street number?

Upvotes: 2

Views: 3022

Answers (3)

Daniil Sencov
Daniil Sencov

Reputation: 36

It works fine for me:

func splitStreetNumber(in streetAddress: String) -> (streetNumber: String?, street: String?) {
    let words = streetAddress.split(separator: " ")
    var lastIndex: Int?
    for (index, word) in words.enumerated() where word.rangeOfCharacter(from: .decimalDigits) != nil {
        lastIndex = index
    }
    guard let lindex = lastIndex else { return (nil, streetAddress) }
    var nChars: [String] = []
    var sChars: [String] = []
    for (index, word) in words.enumerated() {
        if index <= lindex {
            nChars.append(String(word))
        } else {
            sChars.append(String(word))
        }
    }
    let number = nChars.joined(separator: " ")
    let street = sChars.joined(separator: " ")
    return (number.isEmpty ? nil : number, street.isEmpty ? nil : street)
}

Upvotes: 0

Scott Levie
Scott Levie

Reputation: 91

Using a regular expression you can get both the street number and street from the thoroughfare in one go. This makes your address parsing code much more flexible because you will only have to make minimal changes in the splitStreetNumber(in:) method if you decide to tweak it later. Also the substrings method is extremely reusable.

extension NSRegularExpression {

    func substrings(in string: String, options: MatchingOptions = [], range rangeOrNil: NSRange? = nil) -> [[String?]] {

        // search the full range of the string by default
        let range = rangeOrNil ?? NSRange(location: 0, length: string.count)
        let matches = self.matches(in: string, options: options, range: range)

        // parse each match's ranges into strings
        return matches.map{ match -> [String?] in

            return (0..<match.numberOfRanges)
                // map each index to a range
                .map{ match.range(at: $0) }
                // map each range to a substring of the given string if the range is valid
                .map{ matchRange -> String? in
                    if let validRange = range.intersection(matchRange) {
                        return (string as NSString).substring(with: validRange)
                    }
                    return nil
            }
        }
    }
}

func splitStreetNumber(in streetAddress: String) -> (streetNumber: String?, street: String?) {

    // regex matches digits at the beginning and any text after without capturing any extra spaces
    let regex = try! NSRegularExpression(pattern: "^ *(\\d+)? *(.*?) *$", options: .caseInsensitive)

    // because the regex is anchored to the beginning and end of the string there will
    // only ever be one match unless the string does not match the regex at all
    if let strings = regex.substrings(in: streetAddress).first, strings.count > 2 {
        return (strings[1], strings[2])
    }
    return (nil, nil)
}

Result

'  1234 Address Dr  ' -> ('1234', 'Address Dr')
'1234 Address Dr'     -> ('1234', 'Address Dr')
'Address Dr'          -> (nil, 'Address Dr')
'1234'                -> ('1234', nil)

Upvotes: 2

Rashwan L
Rashwan L

Reputation: 38833

The thoroughfare returns the street and street number. Check the GMSAddress documentation.

If you want to get the street number from the thoroughfare result string, you can the method below.

func getStreetNumber(street : String){
     let str = street
     let streetNumber = str.componentsSeparatedByCharactersInSet(
     NSCharacterSet.decimalDigitCharacterSet().invertedSet).joinWithSeparator("")
     print(streetNumber)
}

UPDATE

To get the number only

I have called getStreetNumber("531 W 217th St, New York") and the method below prints out 531.

var number = ""
var hasValue = false

// Loops thorugh the street
for i in street.characters {
    let str = String(i)
    // Checks if the char is a number
    if (Int(str) != nil){
        // If it is it appends it to number
        number+=str
       // Here we set the hasValue to true, beacause the street number will come in one order
       // 531 in this case
       hasValue = true
    }
    else{
        // Lets say that we have runned through 531 and are at the blank char now, that means we have looped through the street number and can end the for iteration
        if(hasValue){
            break
        }
   }
}
print(number)

To get the address only

func getStreetNumber(street : String){
        let str = street
        let streetNumber = str.componentsSeparatedByCharactersInSet(
            NSCharacterSet.decimalDigitCharacterSet().invertedSet).joinWithSeparator("")
        print(streetNumber)

        var address = street
        var hasValue = false

        // Loops thorugh the street
        for i in street.characters {
            let str = String(i)
            // Checks if the char is a number
            if (Int(str) != nil){
                // If it is it appends it to number
                address = address.stringByReplacingOccurrencesOfString(str, withString: "", options: NSStringCompareOptions.LiteralSearch, range: nil)
                // Here we set the hasValue to true, beacause the street number will come in one order
                // 531 in this case
                hasValue = true
            }
            else{
                // Lets say that we have runned through 531 and are at the blank char now, that means we have looped through the street number and can end the for iteration
                if(hasValue){
                    break
                }
            }
        }
        print(address)
    }

Upvotes: 1

Related Questions