CoreLocation для Swift: полное руководство с примерами

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Что такое CoreLocation и зачем она нужна?

CoreLocation — это встроенный фреймворк от Apple для платформ iOS, macOS, watchOS и tvOS. Он предоставляет разработчикам доступ к аппаратным и программным средствам определения местоположения устройства. В отличие от сторонних библиотек, CoreLocation не требует установки через менеджеры пакетов (CocoaPods, SPM) — он является частью стандартного SDK.

Основные возможности фреймворка:

  • Определение текущих географических координат (широта и долгота).
  • Отслеживание изменения местоположения в реальном времени.
  • Геозоны (Geofencing) — получение уведомлений при входе/выходе из заданной области.
  • Определение направления (компас) и скорости движения.
  • Обратное геокодирование (преобразование координат в адрес) и прямое геокодирование (адрес в координаты).

Библиотека незаменима для навигационных приложений, сервисов доставки, фитнес-трекеров, социальных сетей с геотегами и любых других приложений, где требуется знать положение пользователя.

Установка CoreLocation

Поскольку CoreLocation является частью операционной системы, его не нужно устанавливать через pip или npm. Для использования достаточно импортировать модуль в код.

Важно: Для работы с геолокацией необходимо добавить описание использования в файл Info.plist вашего проекта. Без этого приложение будет аварийно завершаться при попытке запросить разрешение.

Добавьте один из следующих ключей (в зависимости от того, когда вам нужно местоположение):

  • NSLocationWhenInUseUsageDescription — для доступа только при активном использовании приложения.
  • NSLocationAlwaysAndWhenInUseUsageDescription — для постоянного доступа (даже в фоне).

В качестве значения укажите строку, которая будет показана пользователю в диалоге запроса разрешения (например, "Приложению нужен доступ к геолокации для отображения ближайших кафе").

Быстрый старт с примером кода

Рассмотрим минимальный пример получения текущих координат пользователя.

import CoreLocation

class ViewController: UIViewController, CLLocationManagerDelegate {

    let locationManager = CLLocationManager()

    override func viewDidLoad() {
        super.viewDidLoad()
        locationManager.delegate = self
        locationManager.requestWhenInUseAuthorization()
        locationManager.startUpdatingLocation()
    }

    // MARK: - CLLocationManagerDelegate
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        guard let location = locations.last else { return }
        print("Широта: \(location.coordinate.latitude)")
        print("Долгота: \(location.coordinate.longitude)")
        // Останавливаем обновление, чтобы не расходовать батарею
        locationManager.stopUpdatingLocation()
    }

    func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
        print("Ошибка получения местоположения: \(error.localizedDescription)")
    }
}

Этот код создает менеджер, запрашивает разрешение у пользователя и начинает отслеживание. Как только координаты получены, они выводятся в консоль.

Основные методы/функции CoreLocation

Ниже представлены ключевые методы и свойства класса CLLocationManager, а также вспомогательных классов.

1. requestWhenInUseAuthorization()

Описание: Запрашивает у пользователя разрешение на доступ к геолокации только во время использования приложения (приложение активно на экране).

Параметры: Нет.

Пример:

let manager = CLLocationManager()
manager.requestWhenInUseAuthorization()

2. requestAlwaysAuthorization()

Описание: Запрашивает постоянный доступ к геолокации (даже когда приложение свернуто). Требует дополнительного ключа в Info.plist.

Параметры: Нет.

Пример:

manager.requestAlwaysAuthorization()

3. startUpdatingLocation()

Описание: Запускает генерацию событий обновления местоположения. Менеджер будет вызывать делегат didUpdateLocations каждый раз, когда получает новые данные от GPS или Wi-Fi.

Параметры: Нет.

Пример:

manager.startUpdatingLocation()

4. stopUpdatingLocation()

Описание: Останавливает обновление местоположения. Важно вызывать этот метод, когда данные больше не нужны, чтобы экономить заряд батареи.

Параметры: Нет.

Пример:

manager.stopUpdatingLocation()

5. startMonitoringSignificantLocationChanges()

Описание: Запускает мониторинг только значительных изменений местоположения (например, смена вышки сотовой связи). Потребляет меньше энергии, чем startUpdatingLocation(), но менее точен.

Параметры: Нет.

Пример:

manager.startMonitoringSignificantLocationChanges()

6. startMonitoring(for: CLRegion)

Описание: Начинает мониторинг заданной геозоны (круговой области). При входе или выходе из этой области вызывается соответствующий делегат.

Параметры: region — объект CLCircularRegion, который определяет центр (координаты) и радиус в метрах.

Пример:

let center = CLLocationCoordinate2D(latitude: 55.751244, longitude: 37.618423) // Москва
let region = CLCircularRegion(center: center, radius: 1000, identifier: "MoscowCenter")
region.notifyOnEntry = true
region.notifyOnExit = true
manager.startMonitoring(for: region)

7. requestLocation()

Описание: Однократный запрос текущего местоположения. В отличие от startUpdatingLocation, этот метод не запускает непрерывный поток данных, а вызывает делегат один раз, после чего автоматически останавливает обновления.

Параметры: Нет.

Пример:

manager.requestLocation()

8. distance(from: CLLocation) -> CLLocationDistance

Описание: Метод экземпляра класса CLLocation. Вычисляет расстояние в метрах между двумя географическими точками.

Параметры: from — другая точка CLLocation.

Пример:

let pointA = CLLocation(latitude: 55.7558, longitude: 37.6173)
let pointB = CLLocation(latitude: 59.9343, longitude: 30.3351)
let distance = pointA.distance(from: pointB)
print("Расстояние от Москвы до Питера: \(distance / 1000) км")

9. CLGeocoder().reverseGeocodeLocation(_:completionHandler:)

Описание: Обратное геокодирование — преобразование координат в читаемый адрес (название улицы, города, страны).

Параметры: location — объект CLLocation; completionHandler — замыкание с массивом CLPlacemark или ошибкой.

Пример:

let geocoder = CLGeocoder()
let location = CLLocation(latitude: 48.8566, longitude: 2.3522)
geocoder.reverseGeocodeLocation(location) { placemarks, error in
    guard let placemark = placemarks?.first else { return }
    print("Страна: \(placemark.country ?? "")")
    print("Город: \(placemark.locality ?? "")")
}

10. CLGeocoder().geocodeAddressString(_:completionHandler:)

Описание: Прямое геокодирование — преобразование строки адреса в географические координаты.

Параметры: addressString — строка с адресом; completionHandler — замыкание с массивом CLPlacemark.

Пример:

geocoder.geocodeAddressString("Тверская улица, Москва") { placemarks, error in
    guard let coordinate = placemarks?.first?.location?.coordinate else { return }
    print("Координаты Тверской: \(coordinate.latitude), \(coordinate.longitude)")
}

Реальный практический пример использования

Создадим простое приложение "Мой маршрут", которое отслеживает пройденное расстояние и показывает текущий адрес.

import UIKit
import CoreLocation

class RouteTrackerViewController: UIViewController, CLLocationManagerDelegate {

    let locationManager = CLLocationManager()
    var previousLocation: CLLocation?
    var totalDistance: CLLocationDistance = 0
    let geocoder = CLGeocoder()

    @IBOutlet weak var distanceLabel: UILabel!
    @IBOutlet weak var addressLabel: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()
        locationManager.delegate = self
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        locationManager.requestWhenInUseAuthorization()
        locationManager.startUpdatingLocation()
    }

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        guard let newLocation = locations.last else { return }

        // 1. Считаем расстояние
        if let previous = previousLocation {
            let distance = newLocation.distance(from: previous)
            totalDistance += distance
            distanceLabel.text = String(format: "Пройдено: %.2f м", totalDistance)
        }
        previousLocation = newLocation

        // 2. Получаем адрес
        geocoder.reverseGeocodeLocation(newLocation) { [weak self] placemarks, error in
            guard let placemark = placemarks?.first else { return }
            self?.addressLabel.text = "\(placemark.thoroughfare ?? ""), \(placemark.locality ?? "")"
        }
    }

    func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
        print("Ошибка: \(error.localizedDescription)")
    }
}

В этом примере при каждом обновлении координат мы прибавляем пройденное расстояние к общему и обновляем метку с адресом.

Советы и типичные ошибки

  • Не забывайте про Info.plist: Самая частая ошибка новичков — отсутствие ключа NSLocationWhenInUseUsageDescription. Без него приложение упадет с ошибкой.
  • Экономьте батарею: Не держите startUpdatingLocation() включенным постоянно, если вам не нужны координаты каждую секунду. Используйте requestLocation() для одноразовых запросов или startMonitoringSignificantLocationChanges() для фонового режима.
  • Проверяйте разрешения: Всегда проверяйте статус авторизации через authorizationStatus перед началом работы. Пользователь мог отозвать доступ.
  • Обрабатывайте ошибки: Реализуйте делегат didFailWithError. Если GPS выключен или нет сигнала, приложение должно корректно сообщить пользователю об этом.
  • Тестируйте на реальном устройстве: Симулятор Xcode не имеет GPS. Для тестирования используйте симуляцию местоположения (меню Features -> Location), но финальное тестирование проводите на iPhone или iPad.

Ссылки и ресурсы

Рекомендаций