WedX - журнал о программировании и компьютерных науках

iOS CLLocationManager в отдельном классе

У меня есть несколько контроллеров представления, которым нужно получить местоположение пользователя, поэтому я хотел создать отдельный класс, который ViewControllers может вызывать для получения последнего местоположения пользователя.

locationManager:didUpdateToLocation:fromLocation возвращает значение void. Как передать данные широты и долготы обратно в мои ViewControllers, как только будут рассчитаны широта и долгота пользователя?

Я мог бы попробовать написать геттеры и сеттеры в моем классе locationManaging, но если я это сделаю, как мне узнать, когда вызывать методы получения широты и долготы из моего класса ViewController? Как заставить основной поток ViewController ждать значений широты и долготы из класса locationManaging?

Спасибо!


  • locationManager:didUpdateToLocation:fromLocation — это метод делегата. Диспетчер местоположения использует этот метод, чтобы сообщить вашему объекту, что местоположение было обновлено с новым значением — вы должны реализовать этот метод, чтобы сделать что-то со значением. 17.07.2014

Ответы:


1

Создайте одноэлементный класс, который имеет свойства latitude и longitude, startLocating и endLocating. В классе создайте экземпляр CLLocationManager и установите его делегата в качестве синглтона. В startLocating и endLocating вызовите соответствующие методы экземпляра CLLocationManager. Заставьте методы делегата обновлять свойства latitude и longitude. В другом ViewControllers прочитайте свойства latitude и longitude этого синглтона.

Чтобы знать, когда читать эти свойства из другого ViewController, установите наблюдателя для этих свойств (см. NSKeyValueObserving_Protocol/Reference/Reference.html" rel="noreferrer">Справочник по протоколу NSKeyValueObserving

Прежде чем сделать это, поищите в Интернете существующий код.

После этого загрузите его на GitHub с разрешающей лицензией.

16.07.2012
  • Благодарность! мой дополнительный вопрос: как узнать, когда мой ViewController должен вызывать свойства широты и долготы синглтона? Другими словами, как мне заблокировать основной поток моего ViewController, чтобы дождаться допустимых значений lat long в моем синглтоне 17.07.2012
  • Это во втором абзаце (возможно, я добавил его, пока вы читали мой первоначальный пост) 17.07.2012
  • вы получаете доступ к свойствам синглетонов внутри метода уведомления об изменении наблюдателей 09.09.2015
  • Я попробовал это сегодня. Но мой код не обновлял позицию, пока класс не был объявлен синглтоном. Но почему ? Почему нам нужен синглтон. Я даже не создавал несколько объектов. Я тестировал с одним объектом. 06.06.2016

  • 2

    Как сказал пользователь 1071136, вероятно, вам нужен одноэлементный диспетчер местоположений. Создайте класс, подкласс NSObject, только с одним свойством, CLLocationManager.

    LocationManagerSingleton.h:

    #import <MapKit/MapKit.h>
    
    @interface LocationManagerSingleton : NSObject <CLLocationManagerDelegate>
    
    @property (nonatomic, strong) CLLocationManager* locationManager;
    
    + (LocationManagerSingleton*)sharedSingleton;
    
    @end
    

    LocationManagerSingleton.m:

    #import "LocationManagerSingleton.h"
    
    @implementation LocationManagerSingleton
    
    @synthesize locationManager;
    
    - (id)init {
        self = [super init];
    
        if(self) {
            self.locationManager = [CLLocationManager new];
            [self.locationManager setDelegate:self];
            [self.locationManager setDistanceFilter:kCLDistanceFilterNone];
            [self.locationManager setHeadingFilter:kCLHeadingFilterNone];
            [self.locationManager startUpdatingLocation];
            //do any more customization to your location manager
        }
    
        return self;
    }    
    
    + (LocationManagerSingleton*)sharedSingleton {
        static LocationManagerSingleton* sharedSingleton;
        if(!sharedSingleton) {
            static dispatch_once_t onceToken;
            dispatch_once(&onceToken, ^{
                sharedSingleton = [LocationManagerSingleton new];
            }
        }
    
        return sharedSingleton;
    }
    
    - (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
        //handle your location updates here
    }
    
    - (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading {
        //handle your heading updates here- I would suggest only handling the nth update, because they
        //come in fast and furious and it takes a lot of processing power to handle all of them
    }
    
    @end
    

    Чтобы получить последнее полученное местоположение, просто используйте [LocationManagerSingleton sharedSingleton].locationManager.location. Прогрев GPS для определения точного местоположения может занять несколько секунд.

    16.07.2012
  • Возможно, вы захотите обновить свой блок @synchronized до dispatch_once. 19.09.2013
  • @Rickay, будет ли это возвращаться в случае режима полета? 15.01.2014
  • Если вы проверите этот ответ: (stackoverflow.com/questions/7376294/) вы обнаружите, что в этом случае CLLocationManager возвращает последнее полученное местоположение, но не новое местоположение Информация. 16.11.2015

  • 3

    Основываясь на приведенных выше ответах, вот что я сделал, и вы можете найти полный пример на github https://github.com/irfanlone/CLLocationManager-Singleton-Swift

    Просто импортируйте этот файл в свой проект, затем вы можете либо реализовать LocationUpdateProtocol, либо прослушивать уведомления об обновлениях местоположения.

    import MapKit
    
    protocol LocationUpdateProtocol {
        func locationDidUpdateToLocation(location : CLLocation)
    }
    
    /// Notification on update of location. UserInfo contains CLLocation for key "location"
    let kLocationDidChangeNotification = "LocationDidChangeNotification"
    
    class UserLocationManager: NSObject, CLLocationManagerDelegate {
    
        static let SharedManager = UserLocationManager()
    
        private var locationManager = CLLocationManager()
    
        var currentLocation : CLLocation?
    
        var delegate : LocationUpdateProtocol!
    
        private override init () {
            super.init()
            self.locationManager.delegate = self
            self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
            self.locationManager.distanceFilter = kCLLocationAccuracyHundredMeters
            locationManager.requestAlwaysAuthorization()
            self.locationManager.startUpdatingLocation()
        }
    
        // MARK: - CLLocationManagerDelegate
    
        func locationManager(manager: CLLocationManager, didUpdateToLocation newLocation: CLLocation, fromLocation oldLocation: CLLocation) {
            currentLocation = newLocation
            let userInfo : NSDictionary = ["location" : currentLocation!]
    
            dispatch_async(dispatch_get_main_queue()) { () -> Void in
                self.delegate.locationDidUpdateToLocation(self.currentLocation!)
                NSNotificationCenter.defaultCenter().postNotificationName(kLocationDidChangeNotification, object: self, userInfo: userInfo as [NSObject : AnyObject])
            }
        }
    
    }
    

    Использование:

    class ViewController: UIViewController, LocationUpdateProtocol {
    
        var currentLocation : CLLocation!
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            NSNotificationCenter.defaultCenter().addObserver(self, selector: "locationUpdateNotification:", name: kLocationDidChangeNotification, object: nil)
    
            let LocationMgr = UserLocationManager.SharedManager
            LocationMgr.delegate = self
    
        }
    
        // MARK: - Notifications
    
        func locationUpdateNotification(notification: NSNotification) {
            let userinfo = notification.userInfo
            self.currentLocation = userinfo!["location"] as! CLLocation
            print("Latitude : \(self.currentLocation.coordinate.latitude)")
            print("Longitude : \(self.currentLocation.coordinate.longitude)")
    
        }
    
        // MARK: - LocationUpdateProtocol
    
        func locationDidUpdateToLocation(location: CLLocation) {
            currentLocation = location
            print("Latitude : \(self.currentLocation.coordinate.latitude)")
            print("Longitude : \(self.currentLocation.coordinate.longitude)")
        }
    
    }
    
    30.03.2016

    4

    Вот что я сделал при реализации синглтона диспетчера местоположений в Swift. Он основан на стратегии user1071136, а также на быстром шаблоне.

    //
    //  UserLocationManager.swift
    //
    //  Use: call SharedUserLocation.currentLocation2d from any class
    
    
    import MapKit
    
    class UserLocation: NSObject, CLLocationManagerDelegate {
    
        var locationManager = CLLocationManager()
    
        // You can access the lat and long by calling:
        // currentLocation2d.latitude, etc
    
        var currentLocation2d:CLLocationCoordinate2D?
    
    
        class var manager: UserLocation {
            return SharedUserLocation
        }
    
        init () {
            super.init()
            if self.locationManager.respondsToSelector(Selector("requestAlwaysAuthorization")) {
                self.locationManager.requestWhenInUseAuthorization()
            }
            self.locationManager.delegate = self
            self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
            self.locationManager.distanceFilter = 50
            self.locationManager.startUpdatingLocation()
        }
    
        func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {
            self.currentLocation2d = manager.location.coordinate
    
        }
    }
    
    let SharedUserLocation = UserLocation()
    
    16.07.2014
  • Надевайте прихватки при использовании устройства с этим кодом. 17.07.2014
  • В настоящее время я пытаюсь использовать ваш класс, но приложение никогда не запрашивает авторизацию, и я не получаю местоположение. Что мне нужно сделать, чтобы использовать класс? 22.08.2014
  • никогда не забывайте info.plst: stackoverflow. ком/вопросы/24050633/ 23.08.2014
  • @quellish, можете ли вы объяснить свой комментарий .. вы говорите, что это плохое решение - для батареи? Я также думаю о шаблоне для реализации CLLocation для нескольких представлений. 03.11.2015
  • @SamYoungNY этот класс устанавливает точность определения местоположения и фильтр расстояния, чтобы отклонять любые данные о местоположении с точностью менее 50 метров. Это и постоянное включение / выключение обновлений местоположения, как и некоторые другие ответы, вредно для устройства и не помогает приложению. 03.11.2015

  • 5

    В процессе обучения получению местоположения пользователя в одноэлементном классе я скачал этот код https://github.com/irfanlone/CLLocationManager-Singleton-Swift. После того, как я возился с ним, чтобы запустить его на Xcode8.3.3 Swift 3, я не могу получить какие-либо выходные данные в консоли отладки. На самом деле я даже не могу отобразить этот dlalog аутентификации местоположения. Я подозреваю, что данные из синглтона не передаются в контроллер представления, но я не могу исправить решение, вы видите, что не так? Спасибо.

    Исправленный код для Swift 3:

    //The singleton:
    import MapKit
    
    protocol LocationUpdateProtocol {
    func locationDidUpdateToLocation(_ location : CLLocation)
    }
    
    let kLocationDidChangeNotification = "LocationDidChangeNotification"
    
    class UserLocationManager: NSObject, CLLocationManagerDelegate {
    
    static let SharedManager = UserLocationManager()
    
    fileprivate var locationManager = CLLocationManager()
    
    var currentLocation : CLLocation?
    
    var delegate : LocationUpdateProtocol!
    
    fileprivate override init () {
        super.init()
        self.locationManager.delegate = self
        self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
        self.locationManager.distanceFilter = kCLLocationAccuracyHundredMeters
        locationManager.requestAlwaysAuthorization()
        self.locationManager.startUpdatingLocation()
    }
    
    // MARK: - CLLocationManagerDelegate
    func locationManager(manager: CLLocationManager,didUpdateToLocation newLocation: CLLocation, fromLocation oldLocation: CLLocation) {
        currentLocation = newLocation
        let userInfo : NSDictionary = ["location" : currentLocation!]
    
    
        DispatchQueue.main.async() { () -> Void in
            self.delegate.locationDidUpdateToLocation(self.currentLocation!)
            NotificationCenter.default.post(name: Notification.Name(kLocationDidChangeNotification), object: self, userInfo: userInfo as [NSObject : AnyObject])
        }
    }
    
    }
    
    
    
      // The ViewController
        import UIKit
        import CoreLocation
    
     class ViewController: UIViewController, LocationUpdateProtocol {
    
    var currentLocation : CLLocation!
    
    override func viewDidLoad() {
        super.viewDidLoad()
    
        NotificationCenter.default.addObserver(self, selector: #selector(ViewController.locationUpdateNotification(_:)), name: NSNotification.Name(rawValue: kLocationDidChangeNotification), object: nil)
    
        let LocationMgr = UserLocationManager.SharedManager
        LocationMgr.delegate = self
    
    }
    
    // MARK: - Notifications
    
    func locationUpdateNotification(_ notification: Notification) {
        let userinfo = notification.userInfo
        self.currentLocation = userinfo!["location"] as! CLLocation
        print("Latitude : \(self.currentLocation.coordinate.latitude)")
        print("Longitude : \(self.currentLocation.coordinate.longitude)")
    
    }
    
    // MARK: - LocationUpdateProtocol
    
    func locationDidUpdateToLocation(_ location: CLLocation) {
        currentLocation = location
        print("Latitude : \(self.currentLocation.coordinate.latitude)")
        print("Longitude : \(self.currentLocation.coordinate.longitude)")
    }
    
    
    }
    
    12.07.2017
  • Вы должны подумать о том, чтобы задать вопрос самостоятельно, а не публиковать свой вопрос в качестве ответа. 12.07.2017
  • Спасибо за ничего. Если я начинаю новый вопрос с аналогичным названием. вы, парень, заклеймили бы его как дублированный! 13.07.2017
  • Новые материалы

    Я хотел выучить язык программирования MVC4, но не мог выучить его раньше, потому что это выглядит сложно…
    Просто начните и учитесь самостоятельно Я хотел выучить язык программирования MVC4, но не мог выучить его раньше, потому что он кажется мне сложным, и я бросил его. Это в основном инструмент..

    Лицензии с открытым исходным кодом: руководство для разработчиков и создателей
    В динамичном мире разработки программного обеспечения открытый исходный код стал мощной парадигмой, способствующей сотрудничеству, инновациям и прогрессу, движимому сообществом. В основе..

    Объяснение документов 02: BERT
    BERT представил двухступенчатую структуру обучения: предварительное обучение и тонкая настройка. Во время предварительного обучения модель обучается на неразмеченных данных с помощью..

    Как проанализировать работу вашего классификатора?
    Не всегда просто знать, какие показатели использовать С развитием глубокого обучения все больше и больше людей учатся обучать свой первый классификатор. Но как только вы закончите..

    Работа с цепями Маркова, часть 4 (Машинное обучение)
    Нелинейные цепи Маркова с агрегатором и их приложения (arXiv) Автор : Бар Лайт Аннотация: Изучаются свойства подкласса случайных процессов, называемых дискретными нелинейными цепями Маркова..

    Crazy Laravel Livewire упростил мне создание электронной коммерции (панель администратора и API) [Часть 3]
    Как вы сегодня, ребята? В этой части мы создадим CRUD для данных о продукте. Думаю, в этой части я не буду слишком много делиться теорией, но чаще буду делиться своим кодом. Потому что..

    Использование машинного обучения и Python для классификации 1000 сезонов новичков MLB Hitter
    Чему может научиться машина, глядя на сезоны новичков 1000 игроков MLB? Это то, что исследует это приложение. В этом процессе мы будем использовать неконтролируемое обучение, чтобы..


    Для любых предложений по сайту: [email protected]