2015-11-03 8 views
8

Stesso codice, presumo che il dispositivo stia effettivamente aggiornando la posizione due volte per qualche motivo, anche se richiamo una sola volta startUpdatingLocation() e eseguo alcuni stopUpdatingLocations() all'interno di didUpdateLocationslocationManager didUpdateLocations si attiva due volte sul dispositivo, solo una volta sul simulatore

func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { 
    manager.stopUpdatingLocation() 
    let loc: CLLocation = locations[locations.count - 1] 
    let id = 0 
    let type = 0 
    let number = 0 

    createNewDataPoint(id, loc: loc, type: type, number: number) 
} 

In questo caso, createNewDataPoint viene chiamato due volte, creando 2 nuove datapoints. Succede solo una volta nel simulatore, quindi presumo che abbia qualcosa a che fare con il dispositivo reale e il GPS poiché il simulatore simula la sua posizione.

startUpdatingLocation() è presente nel mio codice solo una volta, su un pulsante. Fondamentalmente, si fa clic sul pulsante, vai go manager.startUpdatingLocations(), didUpdateLocations colpisce una volta sul simulatore, due volte sul dispositivo (coordinate identiche) e crea 2 nuovi punti dati.

L'unico altro codice che menziona qualsiasi cosa correlata è l'impostazione dell'accuratezza, del filtro, delle richieste di autorizzazione e di startUpdatingLocation(). C'è qualcosa che posso fare per assicurarmi che non crei il doppio dei punti dati necessari?

+0

Penso che si possa creare una bandiera, accenderlo se ottengono 1 'didUpdateLocations'. Immagino che il problema è che l'aggiornamento di 'CLLocationManager' così veloce, e' stopUpdatingLocation' hanno bisogno di tempo per finire. – anhtu

+1

Sebbene sia ancora necessario utilizzare una delle tecniche suggerite nelle versioni precedenti, suggerisco di controllare ios9 e utilizzare 'requestLocation' in questo caso – Paulw11

risposta

11

I metodi di delegazione del gestore località possono essere chiamati molto frequentemente e in qualsiasi momento.

Si può tuttavia applicarsi seguente algoritmo per salvaguardare se stessi:

  1. Creare un globale bool dicono didFindLocation.
  2. Impostare didFindLocation a false quando si chiama startUpdatingLocation.
  3. All'interno delegato chiamata indietro didUpdateLocations:, se didFindLocation era false, impostare didFindLocation a true e quindi chiamare stopUpdatingLocation.

Spero che questo aiuti.

+0

Soluzione abbastanza semplice. È bello sapere che non è un problema con il mio codice, è solo che la posizione viene aggiornata così rapidamente che si spegne due volte prima che potessi fermarla. Ho anche notato che alcune volte è stato chiamato tre volte. – sdouble

+0

ma non è possibile che il delegato didUpdateLocation venga richiamato prima che venga chiamato stopUpdateingLocaiton? Potrei sbagliarmi qui, ma volevo solo confermare. O il sistema non chiamerà il delegato fino a quando il delegato precedente è ancora in esecuzione? Mi scuso se sono stupido, sono abbastanza nuovo per iOS. Sarebbe un buon progetto aggiungere un blocco in un delegato? – user3508953

+0

La migliore soluzione! È pericoloso impostare il delegato su zero, penso che sia importante tenere traccia del metodo dei delegati, come "locationManager: didChangeAuthorizationStatus:". –

0

Non si ottiene frequentemente sul simulatore. e sul dispositivo quando ti trasferirai lontano, solo tu avrai didUpdateLocations. basta spostarsi in uno spazio aperto in modo che il GPS possa identificare la posizione del dispositivo in modo da ottenere la massima precisione.

7

Il modo migliore è fare come segue:

func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { 
    manager.stopUpdatingLocation() 
    manager.delegate = nil 
} 
+0

Grazie amico per questa risposta più semplice –

5

migliore soluzione per iOS 10.0+

- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations { 
    [locationManager stopUpdatingLocation]; // stop location manager 
    locationManager.delegate = nil; 
    //Your logics... 
    //This will be called only one time now. 
} 

Ma non dimenticate di impostare di nuovo il delegato.

+0

L'impostazione del delegato su zero è la parte più importante! –

0

invece di iniziare/terminare l'aggiornamento posizione e l'impostazione delegato a zero, c'è un metodo chiamato requestLocation che è l'ideale quando l'applicazione necessita di soluzione rapida sulla posizione dell'utente:

Dalla documentazione:

override func viewDidLoad() { 
    // Create a location manager object 
    self.locationManager = CLLocationManager() 

    // Set the delegate 
    self.locationManager.delegate = self 
} 

func getQuickLocationUpdate() { 
    // Request location authorization 
    self.locationManager.requestWhenInUseAuthorization() 

    // Request a location update 
    self.locationManager.requestLocation() 
    // Note: requestLocation may timeout and produce an error if authorization has not yet been granted by the user 
} 

func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { 
    // Process the received location update 
} 

Utilizzare questo metodo quando si desidera la posizione corrente dell'utente ma non è necessario lasciare i servizi di localizzazione in esecuzione.

0

soluzione @Zumry Mohamed s' è giusto

provo il codice come questo:

- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations { 

    [self.locationManager stopUpdatingLocation]; 
    self.locationManager.delegate = nil; 
    self.locationManager = nil; 
} 

finalmente questo delegato viene chiamato solo una volta, ho capito ora perché si è verificato il problema, proprio perché responsabile chiama il metodo stopUpdatingLocation ma il sistema non ci aiuta a rendere il delegato non valido, quindi possiamo ricevere la richiamata ogni volta che si aggiorna la posizione a causa delle tue desiredAccuracy e distanceFilter impostazioni di proprietà del tuo CLLocationManager, quindi la soluzione finale è proprio come @Zumry Mohamed detto, possiamo impostare manualmente il d eleggere a zero quando abbiamo stopUpdateLocation. spero che ti aiuterà a capire cosa succede perché questo potrebbe risolvere il problema.

0

Dopo aver ottenuto la latitudine e la longitudine desiderate, è sufficiente chiamare stopUpdatingLocation() e impostare il delegato su nil.

In Swift 3:

locationManager.stopUpdatingLocation() 
locationManager.delegate = nil 

In Objective-C:

[locationManager stopUpdatingLocation] 
locationManager.delegate = nil 

Qui locationManager è l'oggetto del CLLocationManager.

+0

Si prega di formattare il codice. –

0

locationManager.startUpdatingLocation() recupera continuamente il percorso e il metodo didUpdateLocations chiama più volte, Basta impostare il valore per il valore locationManager.distanceFilter prima di chiamare locationManager.startUpdatingLocation().

Come ho impostato a 200 metri (si può cambiare come vostro requisito) lavorando bene

locationManager = CLLocationManager() 
    locationManager.delegate = self 
    locationManager.desiredAccuracy = kCLLocationAccuracyBest 
    locationManager.distanceFilter = 200 
    locationManager.requestWhenInUseAuthorization() 
    locationManager.startUpdatingLocation()