iOS CLLocationManager在单独的类中

iOS CLLocationManager在单独的类中,ios,xcode,core-location,cllocationmanager,Ios,Xcode,Core Location,Cllocationmanager,我有多个视图控制器需要获取用户的位置,所以我想创建一个单独的类,视图控制器可以调用该类来获取用户的最新位置 locationManager:didUpdateToLocation:fromLocation返回无效。如何在计算用户的纬度和经度后立即将纬度和经度数据传递回ViewController 我可以尝试在locationManaging类中编写getter和setter,但如果这样做,我如何知道何时从ViewController类中调用纬度getter和经度getter方法?如何保持View

我有多个视图控制器需要获取用户的位置,所以我想创建一个单独的类,视图控制器可以调用该类来获取用户的最新位置

locationManager:didUpdateToLocation:fromLocation返回无效。如何在计算用户的纬度和经度后立即将纬度和经度数据传递回ViewController

我可以尝试在locationManaging类中编写getter和setter,但如果这样做,我如何知道何时从ViewController类中调用纬度getter和经度getter方法?如何保持ViewController的主线程等待locationManaging类的纬度和经度值


谢谢

创建一个具有
纬度
经度
属性、
惊人定位
结束定位
的单例类。在类中,创建一个
CLLocationManager
实例,并将其委托设置为singleton。在
惊人定位
结束定位
中,调用
CLLocationManager
实例的相应方法。使委托方法更新
纬度
经度
属性。在其他
ViewControllers
中,阅读此单例的
纬度
经度
属性

要知道何时从另一个
ViewController
读取这些属性,请在这些属性上设置观察者(请参阅

在执行此操作之前,请在Internet上查找现有代码


完成此操作后,使用许可证将其上载到GitHub。

正如user1071136所说,单例位置管理器可能就是您想要的。创建一个类,一个NSObject的子类,只需一个属性,
CLLocationManager

LocationManagerSingleton.h:

#import <MapKit/MapKit.h>

@interface LocationManagerSingleton : NSObject <CLLocationManagerDelegate>

@property (nonatomic, strong) CLLocationManager* locationManager;

+ (LocationManagerSingleton*)sharedSingleton;

@end

要获取最近接收到的位置,只需使用
[LocationManagerSingleton sharedSingleton].locationManager.location
。可能需要几秒钟的时间来预热GPS以获取准确的位置。

以下是我在swift中实现位置管理器singleton时所做的操作。它基于user1071136的策略,以及


基于以上答案,下面是我所做的,您可以在github上找到完整的示例

只需在项目中导入此文件,然后就可以选择实现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)")
    }

}

在学习在singleton类中获取用户位置的过程中,我下载了这段代码。在Xcode8.3.3 Swift 3上运行它之后,我无法在调试控制台中获得任何输出。事实上,我甚至无法显示此位置验证dlalog。我怀疑singleton中的数据没有传递到view cont罗拉,但我不能确定解决方案,你能看到哪里出了问题吗?谢谢

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


}

谢谢!我的后续问题是..我如何知道我的ViewController何时应该调用singleton的纬度和经度属性?换句话说,我如何锁定ViewController的主线程以等待singleton中的有效lat long值?它在第二段中(可能是在您阅读我的初始帖子时添加的)您可以访问observers change notification方法中的singleton属性。我今天尝试了此操作。但是,在类声明为singleton之前,我的代码没有更新位置。但是为什么?为什么我们需要一个singleton。我甚至没有创建多个对象。我正在使用单个对象进行测试。可能希望将@synchronized块更新为
dispatch\u once
@Rickay在飞机模式下会返回此结果吗?如果您检查此答案:()在这种情况下,您会发现
CLLocationManager
返回最近获取的位置,但不返回新的位置信息。
locationManager:didUpdateToLocation:fromLocation
是一种委托方法。位置管理器使用此方法通知您的对象该位置已使用新值更新-这取决于您若要实现此方法,请对值执行某些操作。使用运行此代码的设备时,请戴上烤箱手套。我当前正在尝试使用您的类,但应用程序从未要求授权,也未获取位置。要使用该类,我需要做些什么?永远不要忘记信息。plst:@quellish您能解释您的评论吗..您是说这是错误的吗一个糟糕的解决方案-对于电池?我正在考虑一种模式来实现多视图的CLLocation。@SamYoungNY这个类正在设置位置精度和距离过滤器,以拒绝精度低于50米的任何位置数据。这和不断地打开/关闭位置更新一样,对t不健康你不需要帮助,你应该考虑问一个问题,而不是把你的问题作为一个答案来发表。谢谢你。我开始了一个类似标题的新问题。
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)")
    }

}
//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)")
}


}