Swift 中的 CLLocation 管理器获取用户的位置

Posted

技术标签:

【中文标题】Swift 中的 CLLocation 管理器获取用户的位置【英文标题】:CLLocation Manager in Swift to get Location of User 【发布时间】:2014-07-26 15:49:38 【问题描述】:

我正在尝试将 ObjC 中的旧应用程序转换为 Swift 作为练习,但遇到了一些问题。我在旧应用程序中使用它的方式是建立 CLLocation 管理器,然后我会使用:

manager = [[CLLocationManager alloc]init];
manager.delegate = self;
manager.desiredAccuracy = kCLLocationAccuracyBest;    
[manager startUpdatingLocation]

自动调用:

-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation

从那里我可以提取我需要的所有信息。但是很快,这种方法没有自动完成功能,我无法弄清楚如何重现它。文档说

startUpdatingLocation()

仍然会被委托调用,但它没有发生。

这是我目前所拥有的:

import UIKit
import corelocation

class ViewController: UIViewController,CLLocationManagerDelegate

@IBOutlet var gpsResult : UILabel

var manager:CLLocationManager!

override func viewDidLoad() 
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    manager = CLLocationManager()
    manager.delegate = self
    manager.desiredAccuracy = kCLLocationAccuracyBest
    manager.startUpdatingLocation()


func locationManager(manager:CLLocationManager, didUpdateLocations locations:AnyObject[]) 
    println("locations = \(locations)")
    gpsResult.text = "success"


任何有关查看位置的帮助或指示将不胜感激。谢谢。

编辑:根据建议更新,但仍然无法正常工作

EDIT2:似乎是一些错误不允许该方法在 ViewController 中正常工作

【问题讨论】:

你可以在这里看到完整的答案:***.com/a/31277543/3166417 edit 2 还有效吗?既然你接受了答案.. 【参考方案1】:

你错过了两件事。首先,您必须使用requestAlwaysAuthorizationrequestWhenInUseAuthorization() 请求许可。所以你的viewDidLoad() 应该是这样的:

var locationManager = CLLocationManager()

override func viewDidLoad() 
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    locationManager.delegate = self
    locationManager.desiredAccuracy = kCLLocationAccuracyBest
    locationManager.requestAlwaysAuthorization()
    locationManager.startUpdatingLocation()

其次,编辑你的Info.plistas indicated here。

【讨论】:

确保 info.plist 中有 ios 8 的有效行,这是我的问题【参考方案2】:

首先在plist文件中添加这两行

    NSLocationWhenInUseUsageDescription

    NSLocationAlwaysUsageDescription

那么这是类工作完成实现这个

import UIKit

import CoreLocation

@UIApplicationMain

class AppDelegate: UIResponder, UIApplicationDelegate, CLLocationManagerDelegate 

var window: UIWindow?
var locationManager: CLLocationManager!
var seenError : Bool = false
var locationFixAchieved : Bool = false
var locationStatus : NSString = "Not Started"

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool 
    initLocationManager();
    return true


// Location Manager helper stuff
func initLocationManager() 
    seenError = false
    locationFixAchieved = false
    locationManager = CLLocationManager()
    locationManager.delegate = self
    locationManager.locationServicesEnabled
    locationManager.desiredAccuracy = kCLLocationAccuracyBest

    locationManager.requestAlwaysAuthorization()


// Location Manager Delegate stuff
// If failed
func locationManager(manager: CLLocationManager!, didFailWithError error: NSError!) 
    locationManager.stopUpdatingLocation()
    if (error) 
        if (seenError == false) 
            seenError = true
           print(error)
        
    


func locationManager(manager: CLLocationManager!, didUpdateLocations locations: AnyObject[]!) 
    if (locationFixAchieved == false) 
        locationFixAchieved = true
        var locationArray = locations as NSArray
        var locationObj = locationArray.lastObject as CLLocation
        var coord = locationObj.coordinate

        println(coord.latitude)
        println(coord.longitude)
    


// authorization status
func locationManager(manager: CLLocationManager!,
    didChangeAuthorizationStatus status: CLAuthorizationStatus) 
        var shouldIAllow = false

        switch status 
        case CLAuthorizationStatus.Restricted:
            locationStatus = "Restricted Access to location"
        case CLAuthorizationStatus.Denied:
            locationStatus = "User denied access to location"
        case CLAuthorizationStatus.NotDetermined:
            locationStatus = "Status not determined"
        default:
            locationStatus = "Allowed to location Access"
            shouldIAllow = true
        
        NSNotificationCenter.defaultCenter().postNotificationName("LabelHasbeenUpdated", object: nil)
        if (shouldIAllow == true) 
            NSLog("Location to Allowed")
            // Start location services
            locationManager.startUpdatingLocation()
         else 
            NSLog("Denied access: \(locationStatus)")
        


【讨论】:

你能告诉我如何在我的 Controller.swift 中使用上述内容吗? 您可以在任何地方使用,只需在您的 viewcontroler 中而不是 appdelegate 中编写此代码。这不会有任何不同。只需从 viewdidload() 调用 InitLocationManager() 其他一切都会一样... 我试过了,但对我不起作用,我发布了一个关于它的问题here。 这就是我的答案。更多信息developer.apple.com/library/ios/documentation/General/Reference/… 此代码有效,但只是第一次,一旦用户接受请求,locationManager.startUpdatingLocation() 就不会在后续应用程序运行中再次调用。【参考方案3】:

我不知道为什么,但似乎startUpdatingLocation 没有在 iOS 7 模拟器上显示用户提示,但是当我手动启用它时,如果我使用较新形式的委托方法,它会按预期工作:

var manager:CLLocationManager!

override func viewDidLoad() 
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    manager = CLLocationManager()
    manager.delegate = self
    manager.desiredAccuracy = kCLLocationAccuracyBest
    manager.startUpdatingLocation()


func locationManager(manager:CLLocationManager, didUpdateLocations locations:[AnyObject])  // Updated to current array syntax [AnyObject] rather than AnyObject[]
    println("locations = \(locations)")

您使用的格式自 iOS 5 或 6 以来已被弃用,因此显然 swift 桥接层根本不支持它。

【讨论】:

对不起,在这种情况下,“手动启用”是什么意思? @大卫 @SeanFitz 进入设置>隐私>位置并确保您的应用已启用。 @SeanFitz 如果您在设备上使用它,只要您不尝试使用已弃用的方法,它似乎就可以正常工作。 我在我的设备上构建了代码,正如您在上面看到的,使用您向我展示的新方法,但 locationManager() 从未从 manager.startUpdatingLocation 调用。它只是完全没有任何作用。 @大卫 @SeanFitz 在现场设备上还是在模拟器上?进入设置>隐私>位置并确保您的应用程序已启用。【参考方案4】:

有同样的问题。 didUpdateLocations - 没有工作。运行您的应用程序。转到设置页面 -> 隐私 -> 位置并关闭定位服务。 didFailWithError 将捕获有关缺少位置服务的错误。然后打开它。从那一刻起,didUpdateLocations 将捕获位置。

【讨论】:

【参考方案5】:

这是我非常简单的代码:

首先在 General/Linked Frameworks and Libraries 中添加 Core Location 框架

然后将以下内容添加到 Info.plist 中:

<key>NSLocationWhenInUseUsageDescription</key>
<string>blablabla</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>blablabla</string>

这是我的 ViewController.swift 文件:

import UIKit
import CoreLocation

class ViewController: UIViewController, CLLocationManagerDelegate 

    var locationManager:CLLocationManager!

    override func viewDidLoad() 
        super.viewDidLoad()

        locationManager = CLLocationManager()
        locationManager.delegate = self
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        locationManager.requestAlwaysAuthorization()
        locationManager.startUpdatingLocation()
    


    func locationManager(manager:CLLocationManager, didUpdateLocations locations: [CLLocation]) 
        print("locations = \(locations)")
    


【讨论】:

【参考方案6】:

对于 Swift 3

import UIKit
import CoreLocation

class ViewController: UIViewController,CLLocationManagerDelegate 


    var locationManager:CLLocationManager!

    override func viewDidLoad() 
        super.viewDidLoad()

        locationManager = CLLocationManager()
        locationManager.delegate = self
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        locationManager.requestAlwaysAuthorization()
        locationManager.startUpdatingLocation()

        // Do any additional setup after loading the view, typically from a nib.
    

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

    func locationManager(_ manager:CLLocationManager, didUpdateLocations locations: [CLLocation]) 
        print("locations = \(locations)")
    



【讨论】:

【参考方案7】:

我希望有两种方法。

var locationManager: CLLocationManager = CLLocationManager()
var initialLocation :CLLocation?
var updatedUserLocation :CLLocation?

override func viewDidLoad() 
    super.viewDidLoad() 

    //MapView Location
    locationManager.delegate = self
    locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
    locationManager.requestWhenInUseAuthorization()
    locationManager.startUpdatingLocation()
    locationManager.startUpdatingHeading()

实现 CLLocationManagerDelegate :

//CLLocationManager Delegate
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) 

    // This only works when user location is updated.
    gpsProviderStatusLabel.changeStatusToOn(gpsProviderStatusLabel)



func locationManager(manager: CLLocationManager, didFailWithError error: NSError) 

    //Error indicates GPS permission restricted

    gpsProviderStatusLabel.changeStatusToOff(gpsProviderStatusLabel)

    //Initial Location
    initialLocation = locations.first

    //Getting Updated Location
    updatedUserLocation = locations.last

检查 CLLocationDelegate 授权:

func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) 

    //This method does real time status monitoring.

        switch status 
        case .NotDetermined:
          print(".NotDetermined")
          break

        case .AuthorizedAlways:
          print(".AuthorizedAlways")
          gpsProviderStatusLabel.changeStatusToOn(gpsProviderStatusLabel)
          break


        case .Denied:
          print(".Denied")
          gpsProviderStatusLabel.changeStatusToOff(gpsProviderStatusLabel)
          break

        case .AuthorizedWhenInUse:
          print(".AuthorizedWhenInUse")
          gpsProviderStatusLabel.changeStatusToOn(gpsProviderStatusLabel)
          break

        case .Restricted:
          print(".Restricted")
          break

        default:
          print("Unhandled authorization status")
          break

        
      

注意:changeStatusToOn 或 changeStatusToOff 是 UILabel 扩展方法,它使标签文本以绿色/红色颜色打开/关闭。

【讨论】:

【参考方案8】:

别忘了添加 NSLocationWhenInUseUsageDescription 或 NSLocationAlwaysUsageDescription 在您的配置文件中(目标/信息/自定义 iOS 目标属性

【讨论】:

【参考方案9】:

info.plist

中添加 bellow 2 属性
NSLocationWhenInUseUsageDescription : Location information is used for fraud prevention

Privacy - Location Usage Description : Location information is used for fraud prevention

【讨论】:

【参考方案10】:

如果您想默认更新用户位置,而不是每次都点击“模拟位置”,请转到

YourProject-->Build Phases-->Link Binary with libraries-->Add corelocation.framework

当您在模拟器中运行应用程序时,位置会自动/默认更新。在 Swift 2 中测试并运行!

【讨论】:

我只是关注并添加了 corelocation.framework,但它对我不起作用。 不确定它是否是 XCode 特定版本的功能,但我正在使用它来跟踪用户的默认位置,用于天气应用【参考方案11】:

这将请求许可并跟踪是否获得许可,否则退出并发出警报。按下后退按钮时停止跟踪。

info.plist

<key>NSLocationAlwaysUsageDescription</key>
<string>Allow tracking while completing a survey</string>

类:

import UIKit
import CoreLocation    

class LocationViewController: BaseViewController, CLLocationManagerDelegate 

        // MARK: Constants

        private static let enableLocationServices = [
            "title" : "Location",
            "message" : "Enable location services",
            "buttonTitle" : "OK"
        ]

        // MARK: Private variables

        private var manager: CLLocationManager?

        // MARK: UIViewCOntroller methods

        @IBAction func backButtonPressed(sender : UIButton) 
            stopTracking()
            detatchLocationManager()
            dismissViewControllerAnimated(true, completion: nil)
        

        override func viewDidLoad() 
            super.viewDidLoad()

            attachLocationManager()    
        

        // Mark: Location

        func locationManager(manager: CLLocationManager,
                             didChangeAuthorizationStatus status: CLAuthorizationStatus)
        
            if status == .AuthorizedAlways 
                manager.startUpdatingLocation()
             else if status != .NotDetermined 
                showEnableLocationServicesAlert()
            
        

        func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) 
            for location in locations 
                getDependencyService().getProject().appendLocationTrackingFile(location.timestamp, latitude: location.coordinate.latitude, longitude: location.coordinate.longitude)
            
        

        // MARK: LocationViewController

        private func attachLocationManager() 
            manager = CLLocationManager()
            manager?.delegate = self
            manager?.desiredAccuracy = kCLLocationAccuracyBest

            if CLLocationManager.authorizationStatus() != .AuthorizedAlways 
                manager?.requestAlwaysAuthorization()
             else if CLLocationManager.locationServicesEnabled() 
                startTracking()
            
        

        private func detatchLocationManager() 
            manager?.stopUpdatingLocation()
            manager?.delegate = nil
            manager = nil
        

        private func startTracking() 
            manager?.startUpdatingLocation()
        

        private func stopTracking() 
            manager?.stopUpdatingLocation()
        

        private func showEnableLocationServicesAlert() 
getDependencyService().getUiHelper().showAlert(FrogFirstSurveyViewController.enableLocationServices, completion: 
                self.dismissViewControllerAnimated(true, completion: nil)
            )
        

    

【讨论】:

【参考方案12】:

斯威夫特:

添加以下内容

import CoreLocation
class YourViewController: UIViewController

       var locationManager:CLLocationManager!



//MARK:- Location Manager
extension YourViewController: CLLocationManagerDelegate 

    func stratLocationManager()
    
        locationManager = CLLocationManager()
        locationManager.delegate = self
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        self.checkUsersLocationServicesAuthorization()
        locationManager.startUpdatingLocation()

    

    func checkUsersLocationServicesAuthorization()
        /// Check if user has authorized Total Plus to use Location Services
        if CLLocationManager.locationServicesEnabled()
        
            switch CLLocationManager.authorizationStatus()
            
            case .notDetermined:
                // Request when-in-use authorization initially
                // This is the first and the ONLY time you will be able to ask the user for permission
                self.locationManager.delegate = self
                locationManager.requestWhenInUseAuthorization()
                break

            case .restricted, .denied:
                // Disable location features
                PrintLogs("Location Access Not Available")
                break

            case .authorizedWhenInUse, .authorizedAlways:
                // Enable features that require location services here.
                PrintLogs("Location Access Available")
                break
            
        
    

    func locationManager(_ manager:CLLocationManager, didUpdateLocations locations: [CLLocation]) 
        print("locations = \(locations)")
    

【讨论】:

【参考方案13】:

只需调用 init(vc : UIViewController)。

    import Foundation
    import CoreLocation
    import UIKit


    class LocManager : NSObject


        var permission : ((Bool?)->())?

        private var locationManager : CLLocationManager!

        init(_ vc : UIViewController) 
            super.init()
            self.locationManager = CLLocationManager()
            self.locationManager.delegate = vc as? CLLocationManagerDelegate
            setUpLocationManagerDelegate()
        


    

    extension LocManager : CLLocationManagerDelegate 

        fileprivate func setUpLocationManagerDelegate()
               locationManager = CLLocationManager()
               locationManager.delegate = self
               locationManager.desiredAccuracy = kCLLocationAccuracyBest
               locationManager.requestAlwaysAuthorization()
           

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

            if let lat  = locations.last?.coordinate.latitude, let long = locations.last?.coordinate.longitude
                print("\n\nThe current Lat/Long Is Here\n\n")
                let coordinates = CLLocationCoordinate2D(latitude: lat, longitude: long)

            else
                print("Unable To Access Locaion")
            
        

        func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) 

            switch status 
            case .authorizedAlways,.authorizedWhenInUse:
                print("Good to go and use location")
                locationManager.startUpdatingLocation()
                self.callPermisssionCompletion(val: true)

            case .denied:
                print("DENIED to go and use location")
                self.callPermisssionCompletion(val: false)

            case .restricted:
                print("DENIED to go and use location")
                self.callPermisssionCompletion(val: nil)

            case .notDetermined:
                print("DENIED to go and use location")
                self.callPermisssionCompletion(val: nil)

            default:
                print("Unable to read location :\(status)")
            
        


        fileprivate func callPermisssionCompletion(val : Bool?)

            guard let comp = self.permission else 
                print("\n\n Unable to  locate completions \n\n")
                return
            
            if let val =  val
                comp(val)
            

        


    

【讨论】:

以上是关于Swift 中的 CLLocation 管理器获取用户的位置的主要内容,如果未能解决你的问题,请参考以下文章

Apple 的 CLLocation 管理器的外部 NMEA GPS

如何在位置管理器功能swift 3中使用用户位置

swift Swift - 扩展到CLLocation以获取坐标的笛卡尔表示。来源:http://stackoverflow.com/a/5983282/273119

swift Swift - 扩展到CLLocation以获取坐标的笛卡尔表示。来源:http://stackoverflow.com/a/5983282/273119

swift Swift - 扩展到CLLocation以获取坐标的笛卡尔表示。来源:http://stackoverflow.com/a/5983282/273119

swift Swift - 扩展到CLLocation以获取坐标的笛卡尔表示。来源:http://stackoverflow.com/a/5983282/273119