如何从GMSPlace地址组件中提取街道,城市等

时间:2017-05-22 12:33:18

标签: ios swift3 google-places-api

我使用适用于iOS的Google Places API,可以成功检索附近的地方并将地址显示为字符串。我想要做的是提取地址组件,例如city来存储在数据库中。

文档表明GMSPlace有一个addressComponents属性(一个数组),但我似乎无法想象如何使用这个属性。

下面的代码提供了标签文本的整个地址,但我无法超越:

编辑----添加了代码,显示了我如何尝试访问地址组件

venueLabel.isHidden = false
            venueLabel.text = selectedPlace?.name
            addressLabel.isHidden = false
            addressLabel.text = selectedPlace?.formattedAddress
            let addressComponents = selectedPlace?.addressComponents
            for component in addressComponents! {
                let city = component["city"] //Error Type GMSPaceAddressComponent has no subscript members
                print(city)
            }

10 个答案:

答案 0 :(得分:10)

安全的Swift 4.2解决方案:

let name = place.addressComponents?.first(where: { $0.type == "city" })?.name

selectedPlace.addressComponents是 GMSAddressComponent 的数组,它有2个属性类型和名称。 在你的情况下,它将像

    for component in addressComponents! {
    if component.type == "city" {
    print(component.name)
    }
   }

GMSAddressComponent是一个类,而不是您收到此错误的字典或数组。

可以从link引用其他组件类型。

答案 1 :(得分:3)

Swift 4

    var keys = [String]()
    place.addressComponents?.forEach{keys.append($0.type)}
    var values = [String]()
    place.addressComponents?.forEach({ (component) in
        keys.forEach{ component.type == $0 ? values.append(component.name): nil}
    })
    print(values) 

答案 2 :(得分:2)

对于最新的Google Places API(2019年7月),这可以为您提供帮助。 实际上,Google现在为每个元素添加了几种类型。因此,现在不建议使用“类型”,而要提交新的“类型”。

您可以执行以下操作:

 for addressComponent in (self.mySelectedPlace?.addressComponents)! {
            for type in (addressComponent.types){

                switch(type){
                    case "country":
                        var country = addressComponent.name

                    case "postal_code":
                         var postCode = addressComponent.name

                default:
                    break
                }

            }
        }

答案 3 :(得分:1)

对于那些追随我的人来说,我无法在Objective-C的任何地方找到它:

for (int i = 0; i < [place.addressComponents count]; i++)
{
    NSLog(@"name %@ = type %@", place.addressComponents[i].name, place.addressComponents[i].type);
}

答案 4 :(得分:1)

我正在使用此扩展程序:

extension Array where Element == GMSAddressComponent {
    func valueFor(placeType: String, shortName: Bool = false) -> String? {
        // bug in the google or apple framework. This cast must stay.
        // Withou it crashing.
        guard let array = self as? NSArray else { return nil }
        let result = array
            .compactMap { $0 as? GMSAddressComponent }
            .first(where: {
                $0.types
                    .first(where: { $0 == placeType }) == placeType
            })
        return shortName ? result?.shortName : result?.name
    }
}

用法:

let place: GMSPlace
// ...
place.addressComponents?.valueFor(placeType: kGMSPlaceTypeRoute, shortName: true)

答案 5 :(得分:1)

我将扩展@Ramis答案,在任何情况下,如果您想检查多种类型(例如其中一种),您都想检查

addressComponents?.valueFor(placeTypes: kGMSPlaceTypePostalTown, kGMSPlaceTypeLocality)

实现

extension Array where Element == GMSAddressComponent {
    func valueFor(placeTypes: String..., shortName: Bool = false) -> String? {
        let array = self as NSArray
        let result = array
            .compactMap { $0 as? GMSAddressComponent }
            .first(where: {
                placeTypes.contains($0.types.first(where: { placeTypes.contains($0) }) ?? "")
            })
        return shortName ? result?.shortName : result?.name
    }
}

答案 6 :(得分:1)

它可以在Swift 5和iOS 13.3中运行

1。创建一个用于显示GMSAutocompleteViewController的函数

    func googlePlacesSearchVC() {
    
        let acController = GMSAutocompleteViewController()
        acController.delegate = self
        // Specify the place data types to return.
        let fields: GMSPlaceField = GMSPlaceField(rawValue: UInt(GMSPlaceField.name.rawValue) |
      UInt(GMSPlaceField.formattedAddress.rawValue)  |
               UInt(GMSPlaceField.addressComponents.rawValue))!
    
        acController.placeFields = fields
        // Specify a filter.
        let filter = GMSAutocompleteFilter()
        filter.country = "IN"
        acController.autocompleteFilter = filter

        acController.secondaryTextColor = .darkGray
        acController.primaryTextColor = .lightGray
        acController.primaryTextHighlightColor = .black
        acController.tableCellBackgroundColor = .whiteThree
        acController.tableCellSeparatorColor = .lightGray
        // Display the autocomplete view controller.
        present(acController, animated: true) {

            let views = acController.view.subviews
            let subviewsOfSubview = views.first!.subviews
            let subOfNavTransitionView = subviewsOfSubview[1].subviews
            let subOfContentView = subOfNavTransitionView[1].subviews
            let searchBar = subOfContentView[0] as! UISearchBar
            searchBar.searchTextField.placeholder = "places_picker_hint_add_address".localized
            searchBar.searchBarStyle = .minimal
            searchBar.searchTextField.font = UIFont.screenTitle16Pt
            searchBar.searchTextField.backgroundColor = UIColor.white
            searchBar.searchTextField.leftView?.tintColor = .darkGray
            searchBar.delegate?.searchBar?(searchBar, textDidChange: "")
        }
   }

2。在任何需要的地方调用该函数,例如:-

   override func viewDidLoad() {
      super.viewDidLoad()

      googlePlacesSearchVC()
   }

3。调用GMSAutoCompleteViewControllerDelegates方法。 这里将从GMSPlace地址组件获取所有详细信息,例如街道,城市等

extension ViewController {

      // Handle the user's selection.
      func viewController(_ viewController: GMSAutocompleteViewController, didAutocompleteWith place: GMSPlace) {
        
            // Show HouseAndFlat
            if place.name?.description != nil {
                
                yourTxtField.text = place.name?.description ?? ""
            }

            // Show latitude
            if place.coordinate.latitude.description.count != 0 {
                var latitude = place.coordinate.latitude
            }
            // Show longitude
            if place.coordinate.longitude.description.count != 0 {
                selectedLongitude = place.coordinate.longitude
            }

            // Show AddressComponents
            if place.addressComponents != nil {
                
                for addressComponent in (place.addressComponents)! {
                   for type in (addressComponent.types){

                       switch(type){
                           case "sublocality_level_2":
                               yourTxtField.text = addressComponent.name
                           case "sublocality_level_1":
                                yourTxtField.text = addressComponent.name
                            case "administrative_area_level_2":
                                yourTxtField.text = addressComponent.name

                            case "administrative_area_level_1":
                                 yourTxtField.text = addressComponent.name
                            case "country":
                                yourTxtField.text = addressComponent.name

                            case "postal_code":
                                 yourTxtField.text = addressComponent.name
                       default:
                           break
                       }
                   }
               }
            }
            dismiss(animated: true, completion: nil)
      }

      func viewController(_ viewController: GMSAutocompleteViewController, didFailAutocompleteWithError error: Error) {
            // TODO: handle the error.
            print("Error: ", error.localizedDescription)
      }

      // User canceled the operation.
      func wasCancelled(_ viewController: GMSAutocompleteViewController) {
            dismiss(animated: true, completion: nil)
      }
}

I have found an answer from this link

答案 7 :(得分:0)

for ( GMSAddressComponent * component in place.addressComponents) {
    if ( [component.type  isEqual: @"locality"] )
    {
        NSLog(@"Current city %@ ", component.name);
    }
}

答案 8 :(得分:0)

var keys = [String]()
    place.addressComponents?.forEach{keys.append($0.type)}
    var values = [String]()
    place.addressComponents?.forEach({ (component) in
        keys.forEach{ component.type == $0 ? values.append(component.name): nil}

         print("All component type \(component.type)")

       if component.type == "locality"{
            print("This is city name \(component.name)")
        }
    })
    print(values)

答案 9 :(得分:-1)

我找到了,希望对你有帮助

  let arrays : NSArray = place.addressComponents! as NSArray
        for i in 0..<arrays.count {

            let dics : GMSAddressComponent = arrays[i] as! GMSAddressComponent
            let str : NSString = dics.type as NSString

            if (str == "country") {
                print("Country: \(dics.name)")
                self.pais = dics.name
            }

            else if (str == "administrative_area_level_2") {
                print("City: \(dics.name)")
                self.ciudad = dics.name
            }