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

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

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

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

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

Спасибо!

4b9b3361

Ответ 1

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

Чтобы узнать, когда читать эти свойства из другого ViewController, установите наблюдателя на эти свойства (см. Справка протокола NSKeyValueObserving

Перед тем, как сделать это, найдите Интернет файлы для существующего кода.

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

Ответ 2

Как сказал user1071136, одноранговый менеджер местоположений, вероятно, вы хотите. Создайте класс, подкласс 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.

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

}

Ответ 4

Вот то, что я сделал при реализации локального синтаксиса location в 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()

Ответ 5

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

Скорректированный код для Swift 3: // Синглтон:   импортировать MapKit

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

}

//ViewController   импортировать UIKit import CoreLocation

класс 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)")
}

}