Подтвердить что ты не робот

Менеджер CLLocation в Swift, чтобы получить местоположение пользователя

Я пытаюсь преобразовать старое приложение в 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"
}
}

Любая помощь или указатели на то, где искать, будут оценены. Спасибо.

EDIT: Обновлено из предложений, но все еще не работает

EDIT2: Кажется, есть некоторая ошибка, не позволяющая методу работать должным образом в ViewController

4b9b3361

Ответ 1

Вам не хватает двух вещей. Во-первых, вы должны спросить разрешения с помощью requestAlwaysAuthorization или requestWhenInUseAuthorization(). Таким образом, ваш viewDidLoad() должен выглядеть следующим образом:

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    locationManager = CLLocationManager()
    locationManager.delegate = self
    locationManager.desiredAccuracy = kCLLocationAccuracyBest
    locationManager.requestAlwaysAuthorization()
    locationManager.startUpdatingLocation()
}

Во-вторых, отредактируйте Info.plist как указано здесь.

Ответ 2

Сначала добавьте две строки в файл plist

1) NSLocationWhenInUseUsageDescription

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

Ответ 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, поэтому, по-видимому, он вообще не поддерживается быстрыми слоями моста.

Ответ 4

была та же проблема. didUpdateLocations - не работал. Запустите приложение. Перейдите на страницу "Настройки" → "Конфиденциальность" → "Расположение" и "Отключить службы местоположения". didFailWithError поймает ошибку об отсутствующих службах местоположения. Затем включите его. С того момента didUpdateLocations будет захватывать местоположения.

Ответ 5

Вот мой очень простой код, который работает:

сначала добавьте инфраструктуру 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

не забудьте добавить NSLocationWhenInUseUsageDescription или NSLocationAlwaysUsageDescription в вашем файле конфигурации (целевые/Info/пользовательские целевые свойства iOS

Ответ 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 Extenion, который делает текст метки вкл./выкл. зеленым/красным цветом.

Ответ 8

Для 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)")
    }


}

Ответ 9

Добавьте следующее свойство 2 в info.plist

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!

Ответ 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)
            })
        }

    }