Як я можу отримати поточне місцезнаходження від користувача в iOS


Відповіді:


336

Відповідь RedBlueThing працював для мене досить добре. Ось приклад коду того, як я це зробив.

Заголовок

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

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

@end

MainFile

У методі init

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

Функція зворотного дзвінка

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

У iOS 6 функція делегата була застарілою. Новим делегатом є

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

Тому для отримання нової позиції використовуйте

[locations lastObject]

iOS 8

В iOS 8 дозволу слід чітко запитати перед початком оновлення місцезнаходження

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];

Вам також потрібно додати рядок для клавіш NSLocationAlwaysUsageDescriptionабо NSLocationWhenInUseUsageDescriptionклавіші до Info.plist програми. Інакше дзвінки до startUpdatingLocationігноруються, і ваш делегат не отримає зворотного дзвінка.

І наприкінці, коли ви закінчите зчитування розташування виклику stopUpddalization location у відповідному місці.

[locationManager stopUpdatingLocation];

4
+1 спасибі за розміщення простого фрагмента коду для компліменту прийнятій відповіді
AngeloS

12
Будьте обережні з цим прикладом, ці значення властивості призводять до більшого споживання батареї.
DanSkeel

36
ВАЖЛИВО: Вам також потрібно "зупинити оновленняLocations", інакше метод делегата буде викликатися кожен раз, коли користувач змінює своє місцезнаходження. Таким чином, вищезазначена проблема з акумулятором, а також якщо в цьому делегатному методі запускається інший метод, він буде продовжувати дзвонити. Щасливі хлопці з кодування !! Ура !!
Apple_iOS0304

5
Ви тип користувача, який робить StackOverflow чудовим. Фрагменти коду є зразковими, і я сподіваюся, що більше людей включить їх у свої відповіді.
Денні

26
Для iOS 8.0+ ви повинні включити наступні клавіші в Info.plist свого проекту: NSLocationAlwaysUsageDescriptionякщо ви використовуєте [self.locationManager requestAlwaysAuthorization]або NSLocationWhenInUseUsageDescriptionвикористовуєте [self.locationManager requestWhenInUseAuthorization]. Також для підтримки iOS 6.0+ та iOS 7.0+ можна включити ключ NSLocationUsageDescriptionабо "Опис конфіденційності - опис використання місцезнаходження". Більше інформації за посиланням: developer.apple.com/library/ios/documentation/General/Reference/…
Сіхад Бегович

79

В iOS 6, the

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

застаріло.

Замість цього використовуйте наступний код

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

Для iOS 6 ~ 8 вищезазначений метод все ще необхідний, але вам потрібно обробити авторизацію.

_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 
}

Це метод делегата, який обробляє авторизацію користувача

#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
не повинно бути цього [locations lastObject]?
Ян Дундас

1
Я спробував точно такі ж дії, про які говорилося вище. Але я отримую "Користувач все ще думає" надрукований у консолі. Отже, чи означає це, що програма не має права використовувати місцезнаходження? Якщо так, то як я можу дозволити додатку використовувати місцезнаходження. Будь ласка, допоможіть.
kirans_6891

61

Ви використовуєте рамку CoreLocation для доступу до інформації про місцезнаходження свого користувача. Вам потрібно буде створити об'єкт CLLocationManager та викликати повідомлення асинхронного startUpdatingLocation . Ви отримаєте зворотні дзвінки з місцезнаходженням користувача через CLLocationManagerDelegate, який ви постачаєте.


31

Спробуйте ці прості кроки ....

ПРИМІТКА. Будь ласка, перевірте широту та широту розташування пристрою, якщо ви використовуєте засоби імітації. За замовчуванням його немає жодного.

Крок 1: Імпорт CoreLocationрамки у .h файл

#import <CoreLocation/CoreLocation.h>

Крок 2: Додайте делегат CLLocationManagerDelegate

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

Крок 3: Додайте цей код у файл класу

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

Крок 4: Метод виявлення поточного місцезнаходження

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

Крок 5. Отримайте місцезнаходження за допомогою цього методу

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

У Swift (для iOS 8+).

Info.plist

Насамперед. Вам потрібно додати свій описовий рядок у файл info.plist для ключів NSLocationWhenInUseUsageDescriptionабо NSLocationAlwaysUsageDescriptionзалежно від того, яку послугу ви запитуєте

Код

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 = []
    }
}

Використання

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

8
я вважаю, що для таких випадків є перемикач (): ^)
Антон Тропашко,

self.locationManager = LocationManager()використовуйте цей рядок у методі viewDidLoad, щоб ARC не видаляв примірник, а спливаюче вікно для розташування занадто швидко зникає.
Kunal Gupta


2

Ці iOS властивості потребують iOS 11.x Swift 4.0 Info.plist

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

І цей код ... переконайтесь, звичайно, що ваш 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")
    }

І звичайно цей код теж, який ви можете помістити в viewDidLoad ().

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

І ці двоє для запиту Місцеположення, щоб поїхати, він же заощадить вам, що потрібно встати з місця :)

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

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

1

Ви можете використовувати цю службу, яку я написав, щоб обробити все за вас.

Ця послуга вимагає дозволів та обробляє справу з CLLocationManager, тому не потрібно.

Використовуйте так:

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

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

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

0

Для Swift 5, ось короткий короткий клас, щоб отримати місцезнаходження:

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
    }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.