Come posso ottenere la posizione corrente dall'utente in iOS


Risposte:


336

La risposta di RedBlueThing ha funzionato abbastanza bene per me. Ecco un esempio di codice di come l'ho fatto.

Intestazione

#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>

@interface yourController : UIViewController <CLLocationManagerDelegate> {
    CLLocationManager *locationManager;
}

@end

mainfile

Nel metodo init

locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.distanceFilter = kCLDistanceFilterNone;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startUpdatingLocation];

Funzione di richiamata

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
    NSLog(@"OldLocation %f %f", oldLocation.coordinate.latitude, oldLocation.coordinate.longitude);
    NSLog(@"NewLocation %f %f", newLocation.coordinate.latitude, newLocation.coordinate.longitude);
}

iOS 6

In iOS 6 la funzione del delegato era obsoleta. Il nuovo delegato è

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

Pertanto, per ottenere la nuova posizione utilizzare

[locations lastObject]

iOS 8

In iOS 8 è necessario richiedere esplicitamente l'autorizzazione prima di iniziare l'aggiornamento della posizione

locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.distanceFilter = kCLDistanceFilterNone;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
    [self.locationManager requestWhenInUseAuthorization];

[locationManager startUpdatingLocation];

Devi anche aggiungere una stringa per i tasti NSLocationAlwaysUsageDescriptiono NSLocationWhenInUseUsageDescriptional file Info.plist dell'app. In caso contrario, le chiamate a startUpdatingLocationverranno ignorate e il delegato non riceverà alcuna richiamata.

E alla fine, quando hai finito di leggere la posizione, chiama stopUpdating location nel luogo adatto.

[locationManager stopUpdatingLocation];

4
+1 grazie per aver pubblicato un semplice frammento di codice per complimentarmi con la risposta accettata
AngeloS

12
Fai attenzione con questo esempio, questi valori di proprietà comportano un consumo maggiore della batteria.
DanSkeel,

36
IMPORTANTE: è necessario anche "stopUpdatingLocations", altrimenti verrà chiamato il metodo delegato ogni volta che l'utente cambia posizione. Quindi il problema di batteria sopra menzionato e anche se c'è un altro metodo attivato in questo metodo delegato, verrà continuato a chiamare. Happy Coding Guys !! Saluti!!
Apple_iOS0304,

5
Sei il tipo di utente che rende StackOverflow eccezionale. Gli snippet di codice sono esemplari e spero che più persone li includano con le loro risposte.
Danny,

26
Per iOS 8.0+ devi includere le seguenti chiavi in ​​Info.plist del tuo progetto: NSLocationAlwaysUsageDescriptionse stai usando [self.locationManager requestAlwaysAuthorization]o NSLocationWhenInUseUsageDescriptionse stai usando [self.locationManager requestWhenInUseAuthorization]. Anche per supportare iOS 6.0+ a iOS 7.0 e versioni successive includono chiave NSLocationUsageDescriptiono 'privata - Località Utilizzo Descrizione'. Maggiori informazioni sul link: developer.apple.com/library/ios/documentation/General/Reference/…
Sihad Begovic

79

In iOS 6, il

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation

è deprecato.

Utilizzare invece il seguente codice

- (void)locationManager:(CLLocationManager *)manager
     didUpdateLocations:(NSArray *)locations {
    CLLocation *location = [locations lastObject];
    NSLog(@"lat%f - lon%f", location.coordinate.latitude, location.coordinate.longitude);
}

Per iOS 6 ~ 8, il metodo sopra è ancora necessario, ma devi gestire l'autorizzazione.

_locationManager = [CLLocationManager new];
_locationManager.delegate = self;
_locationManager.distanceFilter = kCLDistanceFilterNone;
_locationManager.desiredAccuracy = kCLLocationAccuracyBest;

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0 &&
    [CLLocationManager authorizationStatus] != kCLAuthorizationStatusAuthorizedWhenInUse
    //[CLLocationManager authorizationStatus] != kCLAuthorizationStatusAuthorizedAlways
   ) {
     // Will open an confirm dialog to get user's approval 
    [_locationManager requestWhenInUseAuthorization]; 
    //[_locationManager requestAlwaysAuthorization];
} else {
    [_locationManager startUpdatingLocation]; //Will update location immediately 
}

Questo è il metodo delegato che gestisce l'autorizzazione dell'utente

#pragma mark - CLLocationManagerDelegate
- (void)locationManager:(CLLocationManager*)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
{
    switch (status) {
    case kCLAuthorizationStatusNotDetermined: {
        NSLog(@"User still thinking..");
    } break;
    case kCLAuthorizationStatusDenied: {
        NSLog(@"User hates you");
    } break;
    case kCLAuthorizationStatusAuthorizedWhenInUse:
    case kCLAuthorizationStatusAuthorizedAlways: {
        [_locationManager startUpdatingLocation]; //Will update location immediately
    } break;
    default:
        break;
    }
}

10
questo non dovrebbe essere [locations lastObject]?
Ian Dundas,

1
Ho provato gli stessi identici passaggi sopra menzionati. Ma nella console viene stampato "L'utente sta ancora pensando". Quindi, significa che l'app non è autorizzata a utilizzare la posizione? In caso affermativo, come posso consentire all'app di utilizzare la posizione. Per favore aiuto.
kirans_6891,


31

Prova questi semplici passaggi ....

NOTA: controllare la latitudine e la logitudine della posizione del dispositivo se si utilizzano mezzi simulatore. Di default non è solo.

Passaggio 1: importare il CoreLocationframework nel file .h

#import <CoreLocation/CoreLocation.h>

Passaggio 2: aggiungere delegato CLLocationManagerDelegate

@interface yourViewController : UIViewController<CLLocationManagerDelegate>
{
    CLLocationManager *locationManager;
    CLLocation *currentLocation;
}

Passaggio 3: aggiungere questo codice nel file di classe

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self CurrentLocationIdentifier]; // call this method
}

Passaggio 4: metodo per rilevare la posizione corrente

//------------ Current Location Address-----
-(void)CurrentLocationIdentifier
{
    //---- For getting current gps location
    locationManager = [CLLocationManager new];
    locationManager.delegate = self;
    locationManager.distanceFilter = kCLDistanceFilterNone;
    locationManager.desiredAccuracy = kCLLocationAccuracyBest;
    [locationManager startUpdatingLocation];
    //------
}

Passaggio 5: ottieni la posizione utilizzando questo metodo

- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
    currentLocation = [locations objectAtIndex:0];
    [locationManager stopUpdatingLocation];
    CLGeocoder *geocoder = [[CLGeocoder alloc] init] ;
    [geocoder reverseGeocodeLocation:currentLocation completionHandler:^(NSArray *placemarks, NSError *error)
     {
         if (!(error))
         {
             CLPlacemark *placemark = [placemarks objectAtIndex:0];
             NSLog(@"\nCurrent Location Detected\n");
             NSLog(@"placemark %@",placemark);
             NSString *locatedAt = [[placemark.addressDictionary valueForKey:@"FormattedAddressLines"] componentsJoinedByString:@", "];
             NSString *Address = [[NSString alloc]initWithString:locatedAt];
             NSString *Area = [[NSString alloc]initWithString:placemark.locality];
             NSString *Country = [[NSString alloc]initWithString:placemark.country];
             NSString *CountryArea = [NSString stringWithFormat:@"%@, %@", Area,Country];
             NSLog(@"%@",CountryArea);
         }
         else
         {
             NSLog(@"Geocode failed with error %@", error);
             NSLog(@"\nCurrent Location Not Detected\n");
             //return;
             CountryArea = NULL;
         }
         /*---- For more results 
         placemark.region);
         placemark.country);
         placemark.locality); 
         placemark.name);
         placemark.ocean);
         placemark.postalCode);
         placemark.subLocality);
         placemark.location);
          ------*/
     }];
}

14

In Swift (per iOS 8+).

Info.plist

Cominciando dall'inizio. È necessario aggiungere la stringa descrittiva nel file info.plist per le chiavi NSLocationWhenInUseUsageDescriptiono in NSLocationAlwaysUsageDescriptionbase al tipo di servizio richiesto

Codice

import Foundation
import CoreLocation

class LocationManager: NSObject, CLLocationManagerDelegate {
    
    let manager: CLLocationManager
    var locationManagerClosures: [((userLocation: CLLocation) -> ())] = []
    
    override init() {
        self.manager = CLLocationManager()
        super.init()
        self.manager.delegate = self
    }
    
    //This is the main method for getting the users location and will pass back the usersLocation when it is available
    func getlocationForUser(userLocationClosure: ((userLocation: CLLocation) -> ())) {
        
        self.locationManagerClosures.append(userLocationClosure)
        
        //First need to check if the apple device has location services availabel. (i.e. Some iTouch's don't have this enabled)
        if CLLocationManager.locationServicesEnabled() {
            //Then check whether the user has granted you permission to get his location
            if CLLocationManager.authorizationStatus() == .NotDetermined {
                //Request permission
                //Note: you can also ask for .requestWhenInUseAuthorization
                manager.requestWhenInUseAuthorization()
            } else if CLLocationManager.authorizationStatus() == .Restricted || CLLocationManager.authorizationStatus() == .Denied {
                //... Sorry for you. You can huff and puff but you are not getting any location
            } else if CLLocationManager.authorizationStatus() == .AuthorizedWhenInUse {
                // This will trigger the locationManager:didUpdateLocation delegate method to get called when the next available location of the user is available
                manager.startUpdatingLocation()
            }
        }
        
    }
    
    //MARK: CLLocationManager Delegate methods
    
    @objc func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
        if status == .AuthorizedAlways || status == .AuthorizedWhenInUse {
            manager.startUpdatingLocation()
        }
    }
    
    func locationManager(manager: CLLocationManager, didUpdateToLocation newLocation: CLLocation, fromLocation oldLocation: CLLocation) {
        //Because multiple methods might have called getlocationForUser: method there might me multiple methods that need the users location.
        //These userLocation closures will have been stored in the locationManagerClosures array so now that we have the users location we can pass the users location into all of them and then reset the array.
        let tempClosures = self.locationManagerClosures
        for closure in tempClosures {
            closure(userLocation: newLocation)
        }
        self.locationManagerClosures = []
    }
}

uso

self.locationManager = LocationManager()
self.locationManager.getlocationForUser { (userLocation: CLLocation) -> () in
            print(userLocation)
        }

8
credo che ci sia un interruttore () in tempi rapidi per casi come questo: ^)
Anton Tropashko

self.locationManager = LocationManager()utilizzare questa riga nel metodo viewDidLoad in modo che ARC non rimuova l'istanza e il popup per la posizione scompaia troppo rapidamente.
Kunal Gupta,


2

Info.plist per iOS 11.x Swift 4.0 richiede queste due proprietà

<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>We're watching you</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Watch Out</string>

E questo codice ... assicurandoti ovviamente di essere un CLLocationManagerDelegate

let locationManager = CLLocationManager()

// MARK location Manager delegate code + more

func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
    switch status {
    case .notDetermined:
        print("User still thinking")
    case .denied:
        print("User hates you")
    case .authorizedWhenInUse:
            locationManager.stopUpdatingLocation()
    case .authorizedAlways:
            locationManager.startUpdatingLocation()
    case .restricted:
        print("User dislikes you")
    }

E ovviamente anche questo codice che puoi mettere in viewDidLoad ().

locationManager.delegate = self
locationManager.requestAlwaysAuthorization()
locationManager.distanceFilter = kCLDistanceFilterNone
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestLocation()

E questi due per la richiestaLocation per farti andare, anche per salvarti dal fatto di doverti alzare dal tuo posto :)

func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
    print(error)
}

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

1

Puoi usare questo servizio che ho scritto per gestire tutto per te.

Questo servizio richiederà le autorizzazioni e gestirà la gestione del CLLocationManager in modo da non doverlo fare.

Usa così:

LocationService.getCurrentLocationOnSuccess({ (latitude, longitude) -> () in
    //Do something with Latitude and Longitude

    }, onFailure: { (error) -> () in

      //See what went wrong
      print(error)
})

0

Per Swift 5, ecco una breve breve lezione per ottenere la posizione:

class MyLocationManager: NSObject, CLLocationManagerDelegate {
    let manager: CLLocationManager

    override init() {
        manager = CLLocationManager()
        super.init()
        manager.delegate = self
        manager.distanceFilter = kCLDistanceFilterNone
        manager.desiredAccuracy = kCLLocationAccuracyBest
        manager.requestWhenInUseAuthorization()
        manager.startUpdatingLocation()
    }

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        // do something with locations
    }
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.