xcode iOS CLLocationManager 在一个单独的类中
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11513259/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
iOS CLLocationManager in a separate class
提问by user1467188
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. How do I pass the latitude and longitude data back to my ViewControllers as soon as the user's latitude and longitude is calculated?
locationManager:didUpdateToLocation:fromLocation 返回无效。如何在计算出用户的经纬度后立即将纬度和经度数据传递回我的 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? How do I hold the ViewController's main thread to wait for the latitude and longitude values from the locationManaging class?
我可以尝试在我的 locationManaging 类中编写 getter 和 setter,但是如果我这样做了,我怎么知道何时从我的 ViewController 类中调用纬度 getter 和经度 getter 方法?如何让 ViewController 的主线程等待来自 locationManaging 类的纬度和经度值?
Thanks!
谢谢!
采纳答案by user1071136
Create a singleton class which has a latitude
and longitude
properties, startLocating
and endLocating
. In the class, create a CLLocationManager
instance, and set its delegate to be the singleton. In startLocating
and endLocating
, call the appropriate methods of the CLLocationManager
instance. Make the delegate methods update the latitude
and longitude
properties. In other ViewControllers
, read this singleton's latitude
and longitude
properties.
创建一个具有latitude
和longitude
属性的单例类,startLocating
以及endLocating
。在类中,创建一个CLLocationManager
实例,并将其委托设置为单例。在startLocating
and 中endLocating
,调用CLLocationManager
实例的适当方法。使委托方法更新latitude
和longitude
属性。在其他中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.
在执行此操作之前,请在 Internet 上查找现有代码。
After doing this, upload it to GitHub with a permissive license.
执行此操作后,使用许可许可证将其上传到 GitHub。
回答by eric.mitchell
As user1071136 said, a singleton location manager is probably what you want. Create a class, a subclass of NSObject, with just one property, a CLLocationManager
.
正如 user1071136 所说,单例位置管理器可能是您想要的。创建一个类,一个 NSObject 的子类,只有一个属性,一个CLLocationManager
.
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
. It might take a few seconds to warm up the GPS to get accurate locations.
要获取最近收到的位置,只需使用[LocationManagerSingleton sharedSingleton].locationManager.location
。可能需要几秒钟来预热 GPS 以获得准确的位置。
回答by Irfanlone
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)")
}
}
回答by rgoldfinger
Here's what I did when implementing a location manger singleton in swift. It's based on user1071136's strategy, as well as this swift pattern.
这是我在 swift 中实现位置管理器单例时所做的。它基于 user1071136 的策略,以及这个 swift 模式。
//
// 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()
回答by Rich
In the process of learning to obtain user location in a singleton class, I downloaded this code 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. In fact I can't even get this location autherization dlalog to display. 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.
在单例类中学习获取用户位置的过程中,我下载了这段代码https://github.com/irfanlone/CLLocationManager-Singleton-Swift。在摆弄它以使其在 Xcode8.3.3 Swift 3 上运行后,我无法在调试控制台中获得任何输出。事实上,我什至无法显示这个位置授权 dlalog。我怀疑来自单例的数据没有传递给视图控制器,但我无法解决这个问题,你能看出哪里出了问题吗?谢谢。
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)")
}
}