2013-04-18 17 views
5

Ho iniziato ad aggiornare la posizione corrente quando è stata visualizzata la vista e interrotto l'aggiornamento della posizione ogni volta che viene chiamato locationManager:didUpdateLocations:. Ma perché il locationManager:didUpdateLocations: viene sempre chiamato più volte? Cosa mi sono perso?locationManager: didUpdateLocations: essere sempre chiamato più volte

#import "ViewController.h" 

@interface ViewController(){ 
    CLLocationManager *locationManager; // location manager for current location 
} 
@end 

@implementation ViewController 
- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
} 

- (void)viewDidAppear:(BOOL)animated 
{ 
    [super viewDidAppear:animated]; 
    [self startUpdatingCurrentLocation]; 
} 

- (void)startUpdatingCurrentLocation 
{ 
    if (!locationManager) 
    { 
     locationManager = [[CLLocationManager alloc] init]; 
     [locationManager setDelegate:self]; 
     locationManager.distanceFilter = 10.0f; // we don't need to be any more accurate than 10m 
    } 
    [locationManager startUpdatingLocation]; 
} 

-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{ 
    [locationManager stopUpdatingLocation]; 
} 
@end 
+0

http://stackoverflow.com/questions/22292835/how-to-stop -multiple-times-method-calling-of-didupdatelocations-in-ios – Sanju

risposta

7

Probabilmente dipende dalla precisione impostata sul LocationManager. Hai 3 tipi di localizzazione Cell Radio, WiFi Map, GPS. Se si imposta al meglio la precisione, il responsabile della posizione continuerà a controllare la propria posizione, se la posizione con una precisione migliore è fuori dalla portata del filtro della distanza, verrà richiamato il metodo delegato.

+0

perché [locationManager stopUpdatingLocat ion] non può fermare l'aggiornamento della posizione immediatamente? –

+1

Potrebbe non esserlo, dal momento che le code di posizione provengono da un buffer hardware, ma se il problema esiste è semplicemente una soluzione aggiungere una BOOL statica prima di fermarla e controllarla. Se il tuo BOOL dice che hai già smesso di tornare da quel metodo. – Andrea

+0

Sì, è una soluzione. –

3

SWIFT versione

Ho fatto una classe di supporto come HelperLocationManager e ha aggiunto un modello notification- observer

import UIKit 
import CoreLocation 



class HelperLocationManager: NSObject { 

    var locationManager = CLLocationManager() 
    static let sharedInstance = HelperLocationManager() 
    var currentLocation :CLLocation? 
    var notGotUserLocation = true 

    override init() { 

     super.init() 

     var code = CLLocationManager.authorizationStatus() 

     if code == CLAuthorizationStatus.NotDetermined { 

      locationManager.requestAlwaysAuthorization() 
      locationManager.requestWhenInUseAuthorization() 

     } 
     locationManager.requestAlwaysAuthorization() 
     locationManager.requestWhenInUseAuthorization() 
     locationManager.delegate = self 
     locationManager.distanceFilter = 100; 

    } 


} 


extension HelperLocationManager: CLLocationManagerDelegate{ 


    func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) { 

      var locValue = locations.last as! CLLocation 
      println(locValue) 
      self.currentLocation = locValue 
      NSNotificationCenter.defaultCenter().postNotificationName("sendCurrentAddressToViewController", object:self.currentLocation) 
      notGotUserLocation = false 


    } 

    func locationManager(manager: CLLocationManager!, didFailWithError error: NSError!) { 

     println("Your error is ", error.localizedDescription) 

    } 


} 

Ora, se la classe Viewcontroller ha bisogno la posizione poi mettere un osservatore ci

var helperLocation:HelperLocationManager? 

in viewDidLoad come

 override func viewDidLoad() { 

     helperLocation = HelperLocationManager() 
     NSNotificationCenter.defaultCenter().addObserver(self, selector: "getCurrentAddressToViewController:", name: "sendCurrentAddressToViewController", object: nil) 

    } 

// ed osservatore come

func getCurrentAddressToViewController(notification: NSNotification) { 

     currentLocation = notification.object as? CLLocation 
     NSNotificationCenter.defaultCenter().removeObserver(self, name: "sendCurrentAddressToViewController", object: nil) 

    } 

// anche se didUpdateLocation viene chiamato più volte si ottiene una sola posizione volta a causa della rimozione di observer dopo aver ottenuto la posizione.

EDIT: Ho refractored questa classe di supporto in modo che non avete bisogno di aggiungere notificationobserver modello

class HelperLocationManager: NSObject { 

    private lazy var locationManager = CLLocationManager() 
    static let sharedInstance = HelperLocationManager() 
    var currentLocation :CLLocation? 

    override init() { 

     super.init() 
     locationManager.desiredAccuracy = kCLLocationAccuracyBest 
     locationManager.delegate = self 
    } 
} 

extension HelperLocationManager: CLLocationManagerDelegate{ 

    func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) { 

     switch status { 

     case CLAuthorizationStatus.NotDetermined: 

      locationManager.requestWhenInUseAuthorization() 


     case CLAuthorizationStatus.Restricted: 

      PrinterHelper.messagePrinter("Restricted Access to location") 

     case CLAuthorizationStatus.Denied: 

      PrinterHelper.messagePrinter("User denied access to location") 

     case CLAuthorizationStatus.AuthorizedWhenInUse: 

      if #available(iOS 9.0, *) { 

       locationManager.requestLocation() 

      } else { 

       locationManager.startUpdatingLocation() 
      } 

     default: 

      PrinterHelper.messagePrinter("default authorization") 

     } 
    } 

    func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { 

     let locValue = locations.last 
     HelperLocationManager.sharedInstance.currentLocation = locValue 
     locationManager.stopUpdatingLocation() 

    } 

    func locationManager(manager: CLLocationManager, didFailWithError error: NSError) { 

     PrinterHelper.errorPrinter(error.localizedDescription) 

    } 
} 

View Controller in cui è necessario ottenere Autorizzazione

var helperLocationManager:HelperLocationManager? 

in viewDidLoad come

 override func viewDidLoad() { 

     helperLocationManager = HelperLocationManager.sharedInstance 


    } 

E per ottenere la posizione è necessario chiamare la struttura Singleton currentLocation come

if let userCurentLoc = HelperLocationManager.sharedInstance.currentLocation{ 

      //userCurrentLoc is the user Location 

     } 
0

Per completare il risposta di Anish, se volete sapere quando la classe di supporto non ha chiamato l'aggiornamento della posizione (ad esempio quando si è spento i vostri servizi di localizzazione), è possibile gestire questo utilizzando il metodo locationManager:didChangeAuthorizationStatus:, e se la vostra posizione non è consentito, è possibile chiamare un altro notification- observer

func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) { 
    var shouldIAllow = false 

    switch status { 
    case CLAuthorizationStatus.Restricted: 
     locationStatus = "Restricted Access to location" 
    case CLAuthorizationStatus.Denied: 
     locationStatus = "User denied access to location" 
    case CLAuthorizationStatus.NotDetermined: 
     locationStatus = "Status not determined" 
    default: 
     locationStatus = "Allowed to location Access" 
     shouldIAllow = true 
    } 

    if (shouldIAllow == true) { 
     print("Location to Allowed") 
     // Start location services 
     locationManager!.startUpdatingLocation() 
    } else { 
     print("Denied access: \(locationStatus)") 
     NSNotificationCenter.defaultCenter().postNotificationName("deniedLocation", object:locationStatus) 
    } 
}