IOS CLLocationManager в отдельном классе
У меня есть несколько контроллеров представлений, которые должны получить местоположение пользователя, поэтому я хотел создать отдельный класс, который ViewControllers могут вызвать, чтобы получить последнее место пользователя.
locationManager: didUpdateToLocation: fromLocation возвращает void. Как передать данные широты и долготы обратно в мои ViewControllers, как только будут вычислены широта и долгота пользователя?
Я мог бы попытаться написать геттеры и сеттеры в моем locationManaging class, но если я это сделаю, как узнать, когда вызывать методы getter и longitude getter из моего класса ViewController? Как заставить основной поток ViewController ждать значений широты и долготы из класса locationManaging?
Спасибо!
Ответы
Ответ 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)")
}
}