简体   繁体   English

Swift 中的 CLLocation Manager 来获取用户的位置

[英]CLLocation Manager in Swift to get Location of User

I am trying to convert an old app in ObjC to Swift as a practice exercise and have ran in to some issues.我正在尝试将 ObjC 中的旧应用程序转换为 Swift 作为练习练习,但遇到了一些问题。 The way I had it in the old app, it was establishing the CLLocation Manager and then I would use:我在旧应用程序中使用它的方式是建立 CLLocation Manager,然后我将使用:

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

which would call automatically:它会自动调用:

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

and from there I could extract all the information I needed.从那里我可以提取我需要的所有信息。 But in swift, there is no autocompletion of this method and I cannot figure out how to reproduce it.但是在 swift 中,此方法没有自动完成功能,我无法弄清楚如何重现它。 The documentation says that文档说

startUpdatingLocation()

will still be called by the delegate, but it isn't happening.仍然会被委托调用,但它不会发生。

This is what I have so far:这是我到目前为止:

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"
}
}

Any help or pointers on where to look would be appreciated.任何关于在哪里看的帮助或指示将不胜感激。 Thanks.谢谢。

EDIT: Updated from Suggestions, but still not working编辑:从建议更新,但仍然无法正常工作

EDIT2: Seems to be some bug not allowing the method to work properly in the ViewController EDIT2:似乎是一些错误,不允许该方法在 ViewController 中正常工作

You are missing two things.你错过了两件事。 First, you have to ask for permission using requestAlwaysAuthorization or requestWhenInUseAuthorization() .首先,您必须使用requestAlwaysAuthorizationrequestWhenInUseAuthorization()请求许可。 So your viewDidLoad() should be like this:所以你的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()
}

Second, edit your Info.plist as indicated here .其次,按照此处所示编辑您的Info.plist

First add this two line in plist file首先在plist文件中添加这两行

  1. NSLocationWhenInUseUsageDescription NSLocationWhenInUseUsageDescription

  2. NSLocationAlwaysUsageDescription NSLocationAlwaysUsageDescription

Then this is class working complete implement this然后这是类工作完成实现这个

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)")
        }
}
}

I'm not sure why, but it seems like startUpdatingLocation isn't presenting the user prompt on the iOS 7 simulator, but when I enabled it manually it worked as expected if I used the newer form of the delegate method:我不知道为什么,但似乎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)")
}

The format you're using has been deprecated since iOS 5 or 6, so apparently it's not supported at all by the swift bridging layers.自 iOS 5 或 6 以来,您使用的格式已被弃用,因此显然 swift 桥接层根本不支持它。

had the same issue.有同样的问题。 didUpdateLocations - was not working. didUpdateLocations - 不工作。 Run your app.运行您的应用程序。 Go to the Settings page -> Privacy -> Location and turn off Location Services.转到设置页面 -> 隐私 -> 位置并关闭位置服务。 didFailWithError will catch the error about absent Location Services. didFailWithError 将捕获有关缺少位置服务的错误。 Then turn it on.然后打开它。 Since that moment didUpdateLocations will catch locations.从那一刻起 didUpdateLocations 将捕捉位置。

I hope there are two ways.我希望有两种方法。

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()
}

Implementing CLLocationManagerDelegate :实现 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
}

Checking CLLocationDelegate Authorization:检查 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

        }
      }

Note: changeStatusToOn or changeStatusToOff is a UILabel Extenion method which makes the Label text On/Off with Green/Red Colors.注意:changeStatusToOn 或 changeStatusToOff 是一个 UILabel 扩展方法,它使标签文本打开/关闭绿色/红色。

Here is my very simple code that works:这是我的非常简单的代码:

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

then add following into Info.plist:然后将以下内容添加到 Info.plist 中:

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

this is my ViewController.swift file:这是我的 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)")
    }

}

For Swift 3对于 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)")
    }


}

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

Add bellow 2 property in info.plistinfo.plist 中添加波纹管 2 属性

NSLocationWhenInUseUsageDescription : Location information is used for fraud prevention

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

If you want to get the user location updated by default, without clicking 'Simulate location' everytime, go to如果您希望默认更新用户位置,而不是每次都单击“模拟位置”,请转到

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

The location gets updated automatically/by default when you run the app in the simulator.当您在模拟器中运行应用程序时,位置会自动/默认更新。 Tested and works in Swift 2 !在 Swift 2 中测试和工作!

This will ask for permission and track if given permission else quit with an alert.这将请求许可并跟踪是否获得许可,否则会以警报退出。 Stops tracking on back button press.按下后退按钮时停止跟踪。

info.plist信息.plist

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

Class:班级:

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)
            })
        }

    }

Swift:迅速:

Add following in添加以下内容

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)")
    }
}

Just call the init(vc : UIViewController).只需调用 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)
            }

        }


    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM