2012-07-16 81 views
16

我有多個視圖控制器需要獲取用戶的位置,所以我想創建一個單獨的類,ViewControllers可以調用以獲取用戶的最新位置。iOS CLLocationManager在一個單獨的類

locationManager:didUpdateToLocation:fromLocation返回void。一旦用戶的經度和緯度被計算出來,我如何將緯度和經度數據傳回我的ViewControllers?

我可以嘗試在我的locationManaging類中寫入getter和setter,但如果我這樣做,我該如何知道何時從我的ViewController類調用緯度getter和longitude getter方法?我如何讓ViewController的主線程等待locationManaging類的緯度和經度值?

謝謝!

+0

'的LocationManager:didUpdateToLocation:fromLocation'是委託方法。位置管理器使用此方法通知您的對象該位置已更新爲新值 - 您需要實施此方法才能使用該值執行某些操作。 – quellish 2014-07-16 20:20:46

回答

14

創建一個具有latitudelongitude屬性的單例類,startLocatingendLocating。在該課程中,創建一個CLLocationManager實例,並將其委託設置爲單例。在startLocatingendLocating中,調用CLLocationManager實例的適當方法。使委託方法更新latitudelongitude屬性。在其他ViewControllers中,請閱讀此單例的latitudelongitude屬性。

要知道什麼時候從另一個ViewController讀取這些屬性,設置這些屬性的觀察員(見NSKeyValueObserving Protocol Reference

在此之前,仰望因特網和現有的代碼。

這樣做,上傳後它GitHub上用一個許可證。

+0

謝謝!我的後續問題是..我怎麼知道我的ViewController應該調用單身的緯度和經度屬性?換句話說,我如何鎖定我的ViewController的主線程來等待我的單例中的有效緯度長度值 – user1467188 2012-07-16 22:22:48

+0

它在第二段中(可能在您閱讀我的初始文章時添加了它) – user1071136 2012-07-16 22:24:59

+0

您訪問觀察員更改通知方法 – nilloc 2015-09-09 17:57:49

23

正如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以獲得準確的位置。

+6

可能要將您的@synchronized塊更新爲'dispatch_once'。 – user 2013-09-19 00:43:49

+0

@Rickay會在飛行模式下返回結果嗎? – 2014-01-15 05:44:54

+0

如果你檢查這個答案:(http://stackoverflow.com/questions/7376294/how-is-it-that-c​​llocationmanager-gets-a-location-when-airplane-mode-is-on)你會發現在這種情況下'CLLocationManager'返回最近獲取的位置,但不是新的位置信息。 – 2015-11-16 15:24:38

3

下面是我在swift中實施location manger singleton時所做的工作。它基於user1071136的策略,以及this swift pattern

// 
// 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

使用運行此代碼的設備時,請佩戴烤箱手套。 – quellish 2014-07-16 20:22:10

+0

我目前正在嘗試使用您的班級,但該應用程序從未要求授權,也沒有獲取位置信息。 我需要做什麼來使用課程? – Thomas 2014-08-22 16:07:35

+0

永遠不會忘記info.plst:http://stackoverflow.com/questions/24050633/implement-cllocationmanagerdelegate-methods-in-swift/24056771#24056771 – Thomas 2014-08-22 20:28:57

4

基於以上的答案,這裏是我做的,你可以在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)") 
    } 

} 
0

在學習獲取用戶位置的過程中,我下載了這個代碼https://github.com/irfanlone/CLLocationManager-Singleton-Swift。在使用它在Xcode8.3.3 Swift 3上運行後,我無法在調試控制檯中獲得任何輸出。事實上,我甚至無法得到這個位置認證dlalog顯示。我懷疑來自單身人士的數據沒有傳遞給視圖控制器,但我不能罰款的解決方案,你能看到什麼是錯的?謝謝。

爲夫特3校正後的代碼是: //單元素: 進口MapKit

協議LocationUpdateProtocol { FUNC locationDidUpdateToLocation(_位置:CLLocation) }

讓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 進口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)") 
} 

}

+0

您應該考慮自己提問,而不是將您的問題作爲答案發布。 – stephenmuss 2017-07-12 11:55:53

+0

謝謝。我用相似的標題開始一個新問題。你的傢伙會將它標記爲重複! – Rich 2017-07-12 22:15:25