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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 00:54:54  来源:igfitidea点击:

iOS CLLocationManager in a separate class

iosxcodecore-locationcllocationmanager

提问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 latitudeand longitudeproperties, startLocatingand endLocating. In the class, create a CLLocationManagerinstance, and set its delegate to be the singleton. In startLocatingand endLocating, call the appropriate methods of the CLLocationManagerinstance. Make the delegate methods update the latitudeand longitudeproperties. In other ViewControllers, read this singleton's latitudeand longitudeproperties.

创建一个具有latitudelongitude属性的单例类,startLocating以及endLocating。在类中,创建一个CLLocationManager实例,并将其委托设置为单例。在startLocatingand 中endLocating,调用CLLocationManager实例的适当方法。使委托方法更新latitudelongitude属性。在其他中ViewControllers,阅读这个单身人士的latitudelongitude属性。

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


}