[英]iOS CLLocationManager in a separate class
I have multiple view controllers that need to get the user's location, so I wanted to create a separate class that the ViewControllers can call to get the user's latest location. 我有多个视图控制器需要获取用户的位置,所以我想创建一个单独的类,ViewControllers可以调用该类来获取用户的最新位置。
locationManager:didUpdateToLocation:fromLocation returns void. locationManager:didUpdateToLocation:fromLocation返回void。 How do I pass the latitude and longitude data back to my ViewControllers as soon as the user's latitude and longitude is calculated?
一旦计算出用户的纬度和经度,我如何将纬度和经度数据传回我的ViewControllers?
I could try writing getters and setters in my locationManaging class, but if I do that, how do I know when to call the latitude getter and longitude getter methods from my ViewController class? 我可以尝试在我的locationManaging类中编写getter和setter,但如果我这样做,我怎么知道何时从我的ViewController类中调用latitude getter和longitude getter方法? How do I hold the ViewController's main thread to wait for the latitude and longitude values from the locationManaging class?
如何保持ViewController的主线程等待来自locationManaging类的纬度和经度值?
Thanks! 谢谢!
As user1071136 said, a singleton location manager is probably what you want. 正如user1071136所说,单身人士的位置管理员可能就是你想要的。 Create a class, a subclass of NSObject, with just one property, a
CLLocationManager
. 使用一个属性
CLLocationManager
创建一个类,NSObject的子类。
LocationManagerSingleton.h: LocationManagerSingleton.h:
#import <MapKit/MapKit.h>
@interface LocationManagerSingleton : NSObject <CLLocationManagerDelegate>
@property (nonatomic, strong) CLLocationManager* locationManager;
+ (LocationManagerSingleton*)sharedSingleton;
@end
LocationManagerSingleton.m: 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
To get the most recently received location, simply use [LocationManagerSingleton sharedSingleton].locationManager.location
. 要获取最近收到的位置,只需使用
[LocationManagerSingleton sharedSingleton].locationManager.location
。 It might take a few seconds to warm up the GPS to get accurate locations. 可能需要几秒钟来预热GPS以获得准确的位置。
Create a singleton class which has a latitude
and longitude
properties, startLocating
and endLocating
. 创建一个具有
latitude
和longitude
属性的单例类, startLocating
和endLocating
。 In the class, create a CLLocationManager
instance, and set its delegate to be the singleton. 在类中,创建一个
CLLocationManager
实例,并将其委托设置为单例。 In startLocating
and endLocating
, call the appropriate methods of the CLLocationManager
instance. 在
startLocating
和endLocating
,调用CLLocationManager
实例的相应方法。 Make the delegate methods update the latitude
and longitude
properties. 使委托方法更新
latitude
和longitude
属性。 In other ViewControllers
, read this singleton's latitude
and longitude
properties. 在其他
ViewControllers
,读取此单例的latitude
和longitude
属性。
To know when to read those properties from another ViewController
, set an observer on these properties (see the NSKeyValueObserving Protocol Reference 要知道何时从另一个
ViewController
读取这些属性,请在这些属性上设置观察者(请参阅NSKeyValueObserving协议参考
Before doing this, look up the Internets for existing code. 在此之前,请查找Internets以获取现有代码。
After doing this, upload it to GitHub with a permissive license. 执行此操作后,使用许可许可证将其上载到GitHub。
Based on the above answers, here is what I did and you can find the complete example on github https://github.com/irfanlone/CLLocationManager-Singleton-Swift 根据上面的答案,这就是我所做的,你可以在github上找到完整的例子https://github.com/irfanlone/CLLocationManager-Singleton-Swift
Just import this file in your project, then you can either choose to implement the LocationUpdateProtocol or listen to notification for location updates 只需在项目中导入此文件,然后您可以选择实施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])
}
}
}
Usage: 用法:
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)")
}
}
Here's what I did when implementing a location manger singleton in swift. 这是我在swift中实现位置管理器单例时所做的。 It's based on user1071136's strategy, as well as this swift pattern .
它基于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()
In the process of learning to obtain user location in a singleton class, I downloaded this code https://github.com/irfanlone/CLLocationManager-Singleton-Swift . 在学习获取单例类中的用户位置的过程中,我下载了此代码https://github.com/irfanlone/CLLocationManager-Singleton-Swift 。 After foddleing with it to make in run on Xcode8.3.3 Swift 3, I cannot get any output in the debug console.
在使用Xcode8.3.3 Swift 3进行运行后,我无法在调试控制台中获得任何输出。 In fact I can't even get this location autherization dlalog to display.
实际上我甚至无法显示此位置autherization dlalog。 I suspect the data from the singleton is not passed to the view controller, but I cannot fine the solution, can you see what is wrong?
我怀疑来自单例的数据没有传递给视图控制器,但是我不能解决问题,你能看出什么是错的吗? Thanks.
谢谢。
The corrected code for Swift 3 is: 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)")
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.