【问题标题】:How to retrieve user's current city name?如何检索用户的当前城市名称?
【发布时间】:2010-11-25 20:33:18
【问题描述】:

如何检索用户当前的城市名称?

【问题讨论】:

    标签: iphone objective-c core-location


    【解决方案1】:

    从 iOS 5 开始,MKReverseGeoCoder 已弃用!

    所以您想将CLGeocoderCLLocationManager 一起使用,非常简单并且可以与块一起使用。

    示例:

    - (void)locationManager:(CLLocationManager *)manager
        didUpdateToLocation:(CLLocation *)newLocation
               fromLocation:(CLLocation *)oldLocation
    {
       [self.locationManager stopUpdatingLocation];
    
       CLGeocoder * geoCoder = [[CLGeocoder alloc] init];
        [geoCoder reverseGeocodeLocation:newLocation
                       completionHandler:^(NSArray *placemarks, NSError *error) {
                           for (CLPlacemark *placemark in placemarks) {
                               .... = [placemark locality];
                           }
                       }];
    }
    

    编辑:除了for in 循环,您还可以这样做:

    NSString *locString = placemarks.count ? [placemarks.firstObject locality] : @"Not Found";
    

    【讨论】:

      【解决方案2】:

      您需要做的是设置一个CLLocationManager,它将找到您当前的坐标。使用当前坐标,您需要使用MKReverseGeoCoder 来查找您的位置。

      - (void)viewDidLoad 
      {  
          // this creates the CCLocationManager that will find your current location
          CLLocationManager *locationManager = [[[CLLocationManager alloc] init] autorelease];
          locationManager.delegate = self;
          locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters;
          [locationManager startUpdatingLocation];
      }
      
      // this delegate is called when the app successfully finds your current location
      - (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation 
      {
          // this creates a MKReverseGeocoder to find a placemark using the found coordinates
          MKReverseGeocoder *geoCoder = [[MKReverseGeocoder alloc] initWithCoordinate:newLocation.coordinate];
          geoCoder.delegate = self;
          [geoCoder start];
      }
      
      // this delegate method is called if an error occurs in locating your current location
      - (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error 
      {
       NSLog(@"locationManager:%@ didFailWithError:%@", manager, error);
      }
      
      // this delegate is called when the reverseGeocoder finds a placemark
      - (void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFindPlacemark:(MKPlacemark *)placemark
      {
          MKPlacemark * myPlacemark = placemark;
          // with the placemark you can now retrieve the city name
          NSString *city = [myPlacemark.addressDictionary objectForKey:(NSString*) kABPersonAddressCityKey];
      }
      
      // this delegate is called when the reversegeocoder fails to find a placemark
      - (void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFailWithError:(NSError *)error
      {
          NSLog(@"reverseGeocoder:%@ didFailWithError:%@", geocoder, error);
      }
      

      【讨论】:

      • 一个注意事项:您必须将位置管理器存储在 ivar 中(并且可能在收到位置后再次停止它),否则它将立即自动释放并且您不会收到任何委托回调。此外,反向地理编码器需要互联网连接才能工作。
      • 你能告诉我如何在 Pin 的标题和副标题中打印当前城市或位置吗???
      • @Frade #import
      • MKReverseGeoCoder 自 ios 5.0 起已弃用
      • 弗拉德,我希望你能说出你发现的……叹息
      【解决方案3】:

      这对我来说很好用:

      CLGeocoder *geocoder = [[CLGeocoder alloc] init] ;
      [geocoder reverseGeocodeLocation:self.locationManager.location
                     completionHandler:^(NSArray *placemarks, NSError *error) {
                         NSLog(@"reverseGeocodeLocation:completionHandler: Completion Handler called!");
      
                         if (error){
                             NSLog(@"Geocode failed with error: %@", error);
                             return;
      
                         }
      
      
                         CLPlacemark *placemark = [placemarks objectAtIndex:0];
      
                         NSLog(@"placemark.ISOcountryCode %@",placemark.ISOcountryCode);
                         NSLog(@"placemark.country %@",placemark.country);
                         NSLog(@"placemark.postalCode %@",placemark.postalCode);
                         NSLog(@"placemark.administrativeArea %@",placemark.administrativeArea);
                         NSLog(@"placemark.locality %@",placemark.locality);
                         NSLog(@"placemark.subLocality %@",placemark.subLocality);
                         NSLog(@"placemark.subThoroughfare %@",placemark.subThoroughfare);
      
                     }];
      

      【讨论】:

      • 为什么会返回一个数组?奇怪的。还是谢谢。
      • 这很漂亮,爱块。我会在 placemarks 数组上设置一个条件,以确保 objectatindex:0 确实存在。
      • 你好我收到一个错误kCLErrorDomain error 8你知道为什么吗?
      • CLGeoCoder 未声明我必须做什么,因此它可能会导入什么以及添加什么
      【解决方案4】:

      如果有人试图从 MKReverseGeocoder 迁移到 CLGeocoder,那么我写了一篇博文,可能会有所帮助 http://jonathanfield.me/jons-blog/clgeocoder-example.html

      基本上一个例子是,在您创建 locationManager 和 CLGeocoder 对象之后,只需将此代码添加到您的 viewDidLoad() 中,然后制作一些标签或文本区域来显示数据。

        [super viewDidLoad];
          locationManager.delegate = self;
          [locationManager startUpdatingLocation];
      
          locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
          [self.CLGeocoder reverseGeocodeLocation: locationManager.location completionHandler: 
           ^(NSArray *placemarks, NSError *error) {
      
      
               CLPlacemark *placemark = [placemarks objectAtIndex:0];
      
      
                   isoCountryCode.text = placemark.ISOcountryCode;
                   country.text = placemark.country;
                   postalCode.text= placemark.postalCode;
                   adminArea.text=placemark.administrativeArea;
                   subAdminArea.text=placemark.subAdministrativeArea;
                   locality.text=placemark.locality;
                   subLocality.text=placemark.subLocality;
                   thoroughfare.text=placemark.thoroughfare;
                   subThoroughfare.text=placemark.subThoroughfare;
                   //region.text=placemark.region;
      
      
      
           }];
      

      【讨论】:

      • @macayer 是的,如果为空,崩溃,但如果我理解正确,则永远不会为空。将包含 1 个或多个元素或者是 nil,发送到 nil 的消息会导致 nil,以及通过点符号通过 nil 进行的属性访问。话虽如此,应该始终检查error 是否非nil
      【解决方案5】:

      设置 CLLocationManager 后,您会以纬度/经度对的形式获取位置更新。然后您可以使用 CLGeocoder 将坐标转换为用户友好的地名。

      这是 Swift 4 中的示例代码。

      func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
          if let lastLocation = locations.last {
              let geocoder = CLGeocoder()
      
              geocoder.reverseGeocodeLocation(lastLocation) { [weak self] (placemarks, error) in
                  if error == nil {
                      if let firstLocation = placemarks?[0],
                          let cityName = firstLocation.locality { // get the city name
                          self?.locationManager.stopUpdatingLocation()
                      }
                  }
              }
          }
      }
      

      【讨论】:

        【解决方案6】:

        如果有人在 Swift 3 中需要它,我就是这样做的:

        func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        
            let location = locations.first!
            let coordinateRegion = MKCoordinateRegionMakeWithDistance(location.coordinate, 500, 500)
        
            self.location = location
            self.locationManager?.stopUpdatingLocation()
        
            // Drop a pin at user's Current Location
            let myAnnotation: MKPointAnnotation = CustomPointAnnotation()
            myAnnotation.coordinate = CLLocationCoordinate2DMake(location.coordinate.latitude, location.coordinate.longitude)
            myAnnotation.title = "Localização"
            self.mapViewMK.addAnnotation(myAnnotation)
        
            self.mapViewMK.setRegion(coordinateRegion, animated: true)
            self.locationManager?.stopUpdatingLocation()
            self.locationManager = nil
        
            // Get user's current location name
            let geocoder = CLGeocoder()
            geocoder.reverseGeocodeLocation(self.location!) { (placemarksArray, error) in
        
                if (placemarksArray?.count)! > 0 {
        
                    let placemark = placemarksArray?.first
                    let number = placemark!.subThoroughfare
                    let bairro = placemark!.subLocality
                    let street = placemark!.thoroughfare
        
                    self.addressLabel.text = "\(street!), \(number!) - \(bairro!)"
                }
            }
        }
        

        【讨论】:

          【解决方案7】:

          您必须获取用户的当前位置,然后使用 MKReverseGeocoder 来识别城市。

          iPhone App Programming Guide 第 8 章中有一个很好的例子。 获得位置初始化地理编码器后,设置委托并从地标读取国家/地区。阅读 MKReverseGeocodeDelegate 的文档并创建方法:

          • reverseGeocoder:didFindPlacemark:
          • reverseGeocoder:didFailWithError:

            MKReverseGeocoder *geocoder = [[MKReverseGeocoder alloc] initWithCoordinate:newLocation.coordinate];
            geocoder.delegate = self;
            [geocoder start];
            

          【讨论】:

            【解决方案8】:

            您可以使用此代码获取当前城市:--

            扩展 YourController: CLLocationManagerDelegate { func locationManager(经理:CLLocationManager,didUpdateLocations 位置:[CLLocation]) {

                CLGeocoder().reverseGeocodeLocation(manager.location!, completionHandler: {(placemarks, error)->Void in
            
                    if (error != nil)
                    {
                        manager.stopUpdatingLocation()
                        return
                    }
                    else
                    {
                        if placemarks!.count > 0
                        {
                            let placeMarksArrray: NSArray = placemarks!
                            let pm = placeMarksArrray[0] as! CLPlacemark
                            self.displayLocationInfo(pm)
                            manager.stopUpdatingLocation()
                        } else
                        {
                            print("Problem with the data received from geocoder")
                        }
                    }
                })
            }
            
            func displayLocationInfo(placemark: CLPlacemark!) {
                if (placemark != nil) {
                    //stop updating location to save battery life
                    locationLocation.stopUpdatingLocation()
                    var tempString : String = ""
                    if(placemark.locality != nil){
                        tempString = tempString +  placemark.locality! + " "
                        print(placemark.locality)
                    }
                    if(placemark.postalCode != nil){
                        tempString = tempString +  placemark.postalCode! + " "
                        print(placemark.postalCode)
                    }
                    if(placemark.administrativeArea != nil){
                        tempString = tempString +  placemark.administrativeArea! + " "
                        print(placemark.administrativeArea)
                    }
                    if(placemark.country != nil){
                        tempString = tempString +  placemark.country! + " "
            
            
            
                    }
                    let dictForaddress = placemark.addressDictionary as! NSDictionary
            
            
                    if let city = dictForaddress["City"] {
                        print(city)
            
            
            
                    }
                    strLocation = tempString
                }
            }
            

            【讨论】:

              【解决方案9】:

              这是我的小型 Swift 类,它帮助我获取有关当前位置的反向地理编码信息。不要忘记Info.plist 中的NSLocationWhenInUseUsageDescription 字段。

              class CurrentPlacemarkUpdater: NSObject, CLLocationManagerDelegate {
              
                  private let locationManager = CLLocationManager()
                  private let geocoder = CLGeocoder()
              
                  private(set) var latestPlacemark: CLPlacemark?
                  var onLatestPlacemarkUpdate: (() -> ())?
                  var shouldStopOnUpdate: Bool = true
              
                  func start() {
                      locationManager.requestWhenInUseAuthorization()
                      locationManager.desiredAccuracy = kCLLocationAccuracyKilometer
                      locationManager.delegate = self
                      locationManager.startUpdatingLocation()
                  }
              
                  func stop() {
                      locationManager.stopUpdatingLocation()
                  }
              
                  fileprivate func updatePlacemark(for location: CLLocation) {
                      geocoder.reverseGeocodeLocation(location) { [weak self] placemarks, error in
                          if let placemark = placemarks?.first {
                              self?.latestPlacemark = placemark
                              self?.onLatestPlacemarkUpdate?()
                              if self?.shouldStopOnUpdate ?? false {
                                  self?.stop()
                              }
                          }
                      }
                  }
              
                  func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
                      if let location = locations.last {
                          updatePlacemark(for: location)
                      }
                  }
              
                  func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
                      print("CurrentPlacemarkUpdater: \(error)")
                  }
              
              }
              

              【讨论】:

                【解决方案10】:
                // place the function code below in desire location in program.
                
                // [self getCurrentLocation];
                
                
                
                -(void)getCurrentLocation
                {
                    CLGeocoder *geocoder = [[CLGeocoder alloc] init] ;
                    [geocoder reverseGeocodeLocation:self->locationManager.location
                                   completionHandler:^(NSArray *placemarks, NSError *error) {
                                       NSLog(@"reverseGeocodeLocation:completionHandler: Completion Handler called!");
                
                                       if (error){
                                           NSLog(@"Geocode failed with error: %@", error);
                                           return;
                
                                       }
                
                
                                       CLPlacemark *placemark = [placemarks objectAtIndex:0];
                
                                       NSLog(@"placemark.ISOcountryCode %@",placemark.ISOcountryCode);
                                       NSLog(@"placemark.country %@",placemark.country);
                                        NSLog(@"placemark.locality %@",placemark.locality );
                                       NSLog(@"placemark.postalCode %@",placemark.postalCode);
                                       NSLog(@"placemark.administrativeArea %@",placemark.administrativeArea);
                                       NSLog(@"placemark.locality %@",placemark.locality);
                                       NSLog(@"placemark.subLocality %@",placemark.subLocality);
                                       NSLog(@"placemark.subThoroughfare %@",placemark.subThoroughfare);
                
                                   }];
                }
                

                【讨论】:

                  【解决方案11】:

                  阅读MKReverseGeocoder 的文档——Apple 提供文档、指南和示例应用程序是有原因的。

                  【讨论】:

                  • MKReverseGeoCoder 已弃用
                  猜你喜欢
                  • 2010-11-25
                  • 2013-08-15
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2016-07-29
                  • 1970-01-01
                  • 2010-09-20
                  相关资源
                  最近更新 更多