【问题标题】:How to get current longitude and latitude using CLLocationManager-Swift如何使用 CLLocationManager-Swift 获取当前的经度和纬度
【发布时间】:2014-12-31 17:22:02
【问题描述】:

我想使用 Swift 获取某个位置的当前经度和纬度,并通过标签显示它们。我尝试这样做,但标签上没有显示任何内容。

import UIKit
import CoreLocation
class ViewController: UIViewController, CLLocationManagerDelegate{

    @IBOutlet weak var longitude: UILabel!
    @IBOutlet weak var latitude: UILabel!
    let locationManager = CLLocationManager()

    override func viewDidLoad() {
        super.viewDidLoad()
        if (CLLocationManager.locationServicesEnabled()) {
            locationManager.delegate = self
            locationManager.desiredAccuracy = kCLLocationAccuracyBest
            locationManager.requestWhenInUseAuthorization()
            locationManager.startUpdatingLocation()
        } else {
            println("Location services are not enabled");
        }
    }

    // MARK: - CoreLocation Delegate Methods

    func locationManager(manager: CLLocationManager!, didFailWithError error: NSError!) {
         locationManager.stopUpdatingLocation()
         removeLoadingView()
         if (error) != nil {
             print(error)
          }
     }

    func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {
        var locationArray = locations as NSArray
        var locationObj = locationArray.lastObject as CLLocation
        var coord = locationObj.coordinate
        longitude.text = coord.longitude
        latitude.text = coord.latitude
        longitude.text = "\(coord.longitude)"
        latitude.text = "\(coord.latitude)"
    }
}

【问题讨论】:

标签: ios swift location core-location cllocationmanager


【解决方案1】:

恕我直言,当您正在寻找的解决方案非常简单时,您的代码过于复杂了。

我已经使用以下代码完成了:

首先创建CLLocationManager的实例并请求授权

var locManager = CLLocationManager()
locManager.requestWhenInUseAuthorization()

然后检查用户是否允许授权。

var currentLocation: CLLocation!

if 
   CLLocationManager.authorizationStatus() == .authorizedWhenInUse ||
   CLLocationManager.authorizationStatus() ==  .authorizedAlways
{         
    currentLocation = locManager.location        
}

要使用它,只需这样做

label1.text = "\(currentLocation.coordinate.longitude)"
label2.text = "\(currentLocation.coordinate.latitude)"

您将它们设置为label.text 的想法是正确的,但是我能想到的唯一原因是用户没有授予您权限,这就是您当前的位置数据将为零的原因。

但是,您需要调试并告诉我们。 CLLocationManagerDelegate 也不是必需的。

希望这会有所帮助。如果您有任何疑问,请随时询问。

【讨论】:

  • 你的第二个代码块应该去哪里?在委托方法中?
  • 我通常把它放在“viewdidload”或“awakefromnib”中,但它可以在任何地方使用。只要询问用户使用其位置的权限并且他/她授予它,它就没有限制。
  • 我不同意这个建议。上面的代码甚至没有启动位置管理器——它只是确保它被授权。位置管理员的当前位置读数可能是旧的并且非常不准确。当您激活位置管理器并要求更新位置时,前几个位置结果往往非常糟糕。您确实需要设置一个代表,开始位置更新,并检查您获得的位置更新的准确度读数,直到它们安定下来。
  • @DuncanC 就这样吧。尊重您的意见,此代码对我有用,我将它用于我为客户创建的应用程序的生产中。更直接地说,OP 要求“使用 Swift 获取位置的当前经纬度”。因为显然这对他不起作用。这显然使它起作用,就像对我一样,从而回答了他的问题。如果你想谈谈 LocationManager 的准确性,我的朋友本身就是另一个话题。
  • 在 xcode 9.1 中测试时对我不起作用,在模拟器中,没有委托位置为零。
【解决方案2】:

对于 Swift 3:

首先您需要在info.plist 中设置接收用户 GPS 的限额。

使用随机字符串设置:NSLocationWhenInUseUsageDescription。 和/或:NSLocationAlwaysUsageDescription 带有随机字符串。

然后:

import UIKit
import MapKit

class ViewController: UIViewController {

    var locManager = CLLocationManager()
    var currentLocation: CLLocation!

    override func viewDidLoad() {
        super.viewDidLoad()
        locManager.requestWhenInUseAuthorization()

        if (CLLocationManager.authorizationStatus() == CLAuthorizationStatus.authorizedWhenInUse ||
            CLLocationManager.authorizationStatus() == CLAuthorizationStatus.authorizedAlways){
            guard let currentLocation = locManager.location else {
                return
            }
            print(currentLocation.coordinate.latitude)
            print(currentLocation.coordinate.longitude)
        }
    }
}

完成。

【讨论】:

  • 这段代码在“print(currentLocation.coordinate.latitude)”行给我错误
  • @BijenderSinghShekhawat 是的。请告诉我什么错误。怎么样?
  • @MicroR,是的。
  • 它使用相同的传感器
  • @DavidSeek 对我来说,它总是在保护声明它返回。你能帮我解决这个问题吗?
【解决方案3】:

尽管有其他建议,您应该使用CLLocationManagerDelegate 来安全地检索位置(不使用它,当位置管理器没有足够的时间更新时,您可能会得到空位置)。我强烈建议将位置管理器代码包装在静态共享帮助程序中(类似这些行):

class Locator: NSObject, CLLocationManagerDelegate {
    enum Result <T> {
      case .Success(T)
      case .Failure(ErrorType)
    }

    static let shared: Locator = Locator()

    typealias Callback = (Result <Locator>) -> Void

    var requests: Array <Callback> = Array <Callback>()

    var location: CLLocation? { return sharedLocationManager.location  }

    lazy var sharedLocationManager: CLLocationManager = {
        let newLocationmanager = CLLocationManager()
        newLocationmanager.delegate = self
        // ...
        return newLocationmanager
    }()

    // MARK: - Authorization

    class func authorize() { shared.authorize() }
    func authorize() { sharedLocationManager.requestWhenInUseAuthorization() }

    // MARK: - Helpers

    func locate(callback: Callback) {
        self.requests.append(callback)
        sharedLocationManager.startUpdatingLocation()
    }

    func reset() {
        self.requests = Array <Callback>()
        sharedLocationManager.stopUpdatingLocation()
    }

    // MARK: - Delegate

    func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
        for request in self.requests { request(.Failure(error)) }
        self.reset()
    }

    func locationManager(manager: CLLocationManager, didUpdateLocations locations: Array <CLLocation>) {
        for request in self.requests { request(.Success(self)) }
        self.reset()
    }

}

然后在视图中加载(或您需要获取当前位置的任何其他地方)运行:

Locator.shared.locate { result in
  switch result {
  case .Success(locator):
    if let location = locator.location { /* ... */ }
  case .Failure(error):
    /* ... */
  }
}

【讨论】:

  • 我收到一个错误:“不允许嵌套在类型 'Locator' 中的通用类型 'Result'”。我从未在 Swift 中看到过这个错误。有关修复的任何建议?
  • @ClayEllis 做 enum Result declaration out of class,它会起作用。
  • 按照指令使用,出现错误,例如:使用未解析的标识符“定位器”。进入 UIViewController。
  • 不适用于 Swift 4 和 Xcode 10,请检查一次并编辑您的答案。
  • 尝试在定位器和错误之前添加 let。我希望它有所帮助。 Locator.shared.locate { (result) in switch result { case .success(let locator): break case .failure(let err): break } }
【解决方案4】:

在当前线程中,提出了一个没有委托的解决方案,但在 Xcode 9.1 模拟器中的测试中它不起作用,位置为零。此代码有效:

 import UIKit
 import MapKit

class ViewController: UIViewController, CLLocationManagerDelegate {

var locationManager: CLLocationManager!

override func viewDidLoad() {
    super.viewDidLoad()

    if (CLLocationManager.locationServicesEnabled())
    {
        locationManager = CLLocationManager()
        locationManager.delegate = self
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        locationManager.requestAlwaysAuthorization()
        locationManager.startUpdatingLocation()
    }
}

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation])
{

    let location = locations.last! as CLLocation

    /* you can use these values*/
    let lat = location.coordinate.latitude
    let long = location.coordinate.longitude
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}


}

【讨论】:

    【解决方案5】:

    在 Swift 中

    import UIKit
    import CoreLocation
    
    class ViewController: UIViewController, CLLocationManagerDelegate {
    
        //Labels outlets
    
        @IBOutlet var localityTxtField: UITextField!
        @IBOutlet var postalCodeTxtField: UITextField!
        @IBOutlet var aAreaTxtField: UITextField!
        @IBOutlet var countryTxtField: UITextField!
    
        let locationManager = CLLocationManager()
    
        //View Didload
    
        override func viewDidLoad() {
            super.viewDidLoad()
            // Do any additional setup after loading the view, typically from a nib.
        }
    
         //Button Location
    
        @IBAction func findMyLocation(_ sender: AnyObject) {
            locationManager.delegate = self
            locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
            locationManager.requestWhenInUseAuthorization()
            locationManager.startUpdatingLocation()
        }
    
        func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
            CLGeocoder().reverseGeocodeLocation(manager.location!, completionHandler: {(placemarks, error)->Void in
    
                if (error != nil) {
                    print("Reverse geocoder failed with error" + (error?.localizedDescription)!)
                    return
                }
    
                if (placemarks?.count)! > 0 {
    
                    print("placemarks",placemarks!)
                    let pm = placemarks?[0]
                    self.displayLocationInfo(pm)
                } else {
                    print("Problem with the data received from geocoder")
                }
            })
        }
    
        func displayLocationInfo(_ placemark: CLPlacemark?) {
            if let containsPlacemark = placemark {
    
                print("your location is:-",containsPlacemark)
                //stop updating location to save battery life
                locationManager.stopUpdatingLocation()
                let locality = (containsPlacemark.locality != nil) ? containsPlacemark.locality : ""
                let postalCode = (containsPlacemark.postalCode != nil) ? containsPlacemark.postalCode : ""
                let administrativeArea = (containsPlacemark.administrativeArea != nil) ? containsPlacemark.administrativeArea : ""
                let country = (containsPlacemark.country != nil) ? containsPlacemark.country : ""
    
                localityTxtField.text = locality
                postalCodeTxtField.text = postalCode
                aAreaTxtField.text = administrativeArea
                countryTxtField.text = country
            }
    
        }
    
    
        func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
              print("Error while updating location " + error.localizedDescription)
        }
    }
    

    【讨论】:

      【解决方案6】:

      我是初级但我以这种方式解决了它: 我创建了继承 CLLocationManagerDelegate 的类的扩展并执行以下步骤:

      1.将 CoreLocation 导入到您的 ViewController

      import CoreLocation
      

      2.然后在 ViewController 中初始化位置管理器和位置变量。

      var locManager = CLLocationManager()
      var currentUserLocation: CLLocation!
      
      1. viewDidLoad() 内部请求位置初始化委托和 requestUsageDescription

         locManager.requestWhenInUseAuthorization()
         locManager.delegate = self
         locManager.requestLocation()
        
      2. 然后我刚刚为继承 CLLocationManagerDelegate 的 viewController 创建了扩展

         extension theNameOfYourViewController: CLLocationManagerDelegate{
        
         func locationManager(_ manager: CLLocationManager, didFailWithError error: Swift.Error) {
         print(error)
         }
        
         func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
         // .requestLocation will only pass one location to the locations array
         // hence we can access it by taking the first element of the array
         if let location = locations.first {
         print(location.coordinate.latitude)
         print(location.coordinate.longitude)
        
           }
          }
         }
        

      只要记住在需要位置时根据您的需要更改名称,只需使用功能请求位置

          locManager.requestLocation()
      

      【讨论】:

        【解决方案7】:

        我同意上述 Kevin 的观点,但如果您正在寻找更简单的代码,那么以下内容就足够了: 确保使用CLLocationManagerDelegate

        斯威夫特 4:

        在 viewDidLoad 中可以添加以下内容

         locationManager.requestWhenInUseAuthorization()
        
        
        if (CLLocationManager.authorizationStatus() == CLAuthorizationStatus.authorizedWhenInUse) || (CLLocationManager.authorizationStatus() == CLAuthorizationStatus.authorizedAlways) {
        
                    currentLocation = locationManager.location
                    print(currentLocation.coordinate.latitude)
                    print(currentLocation.coordinate.longitude)
        
                }
        
            }
        

        一旦用户给予或拒绝许可,第一个请求就会响应:

         func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
        
                    if status == .authorizedWhenInUse {
        
                        locationManager.requestLocation()
                        currentLocation = locationManager.location
                        print(currentLocation.coordinate.latitude)
                        print(currentLocation.coordinate.longitude)
                        //Process location information and update.
        
            }
        

        【讨论】:

          【解决方案8】:

          确保将以下键添加到 Info.plist:

          隐私 - 使用时的位置 使用说明 隐私 - 始终定位和使用时使用说明

          创建用户类:

          import Foundation
          import CoreLocation
          import MapKit
          
          class User: NSObject, ObservableObject {
              
              @Published var position =  CLLocationCoordinate2D(latitude: 0.0, longitude: 0.0)
              
              let manager = CLLocationManager()
          
              override init() {
                  super.init()
                  manager.delegate = self
                  manager.requestWhenInUseAuthorization()
                  manager.requestLocation()
              }
              
          }
          
          extension User: CLLocationManagerDelegate {
              
              func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
                  print("Location services authorization request")
              }
              
              func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
                  print("User location updated")
                  print("Updated position: \(locations.first?.coordinate.latitude ?? 00)")
                  
                  if let location = locations.first {
                      self.position = location.coordinate
                  }
              }
              
              func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
                  print("Failed to find user's location: \(error.localizedDescription)")
              }
          
              
          }
          

          【讨论】:

            【解决方案9】:

            更新

            Swift 5+
            Xcode 13+
            

            在信息列表中添加这些权限

            <key>NSLocationWhenInUseUsageDescription</key>
                <string>This app needs your location to show nearby services</string>
            
                <key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
                <string>This app needs your location to show nearby services</string>
            
                <key>NSLocationAlwaysUsageDescription</key>
                <string>This app needs your location to show nearby services</string>
            

            将其导入您的视图控制器

            import CoreLocation
            

            在 viewDidLoad() 中

            override func viewDidLoad() {
                    locationManager.requestWhenInUseAuthorization()
                    locationManager.requestLocation()
            }
            

            像这样创建扩展程序

            extension RegisterViewController : CLLocationManagerDelegate {
            
                func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
                     print("error:: \(error.localizedDescription)")
                }
            
                func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
                    if status == .authorizedWhenInUse {
                        locationManager.requestLocation()
                    }
                }
            
                func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
                    if let locationSafe = locations.last {
                        locationManager.stopUpdatingLocation()
                        let latitude = locationSafe.coordinate.latitude
                        let longitude = locationSafe.coordinate.longitude
                        self.currentLatitude = latitude
                        self.currentLongitude = longitude
                        print(" Lat \(latitude) ,  Longitude \(longitude)")
                        
                    }
                    if locations.first != nil {
                        print("location:: \(locations[0])")
                    }
            
                }
            
            }
            

            运行并检查这个

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2019-10-11
              • 1970-01-01
              • 2011-08-31
              • 2017-05-09
              • 1970-01-01
              • 2023-03-22
              相关资源
              最近更新 更多