Разработка
Оптимизируем обновление местоположения с помощью CLLocationUpdate в Swift
Новый, современный и упрощенный API для получения местоположений от Apple.
На WWDC 23 Apple значительно улучшила процесс обновления местоположения, представив класс CLLocationUpdate. Этот новый класс использует возможности современного Swift Concurrency, упрощая получение и управление данными о местоположении в ваших приложениях.
Что нового?
- Раньше для получения данных о местоположении требовались сложные методы-делегаты и обратные вызовы, что делало наш код менее читабельным и неорганизованным.
- Класс CLLocationUpdate упрощает этот процесс, предоставляя асинхронный подход, использующий функции параллелизма Swift.
- Это означает, что теперь мы можем использовать синтаксис async/await для управления обновлениями местоположения, что делает наш код чище и читабельнее.
- Кроме того, он автоматически приостанавливает/возобновляет обновление местоположения в зависимости от того, движется пользователь или неподвижен.
Почему стоит использовать CLLocationUpdate
- Упрощенный код: синтаксис
async/awaitделает код чище и проще для понимания и тестирования, чем традиционные методы с делегатами и колбеками. - Улучшенная читаемость: код становится организованным и читабельным и помещает все компоненты в одно место, что позволяет больше сосредоточиться на фактической логике обработки местоположения.
- Обработка ошибок: поскольку мы можем использовать
async/awaitв этом методе, мы можем использовать блокtry/catchвнутри цикла для простой обработки ошибок. - Поддержка параллелизма: поскольку местоположение предоставляется в виде
AsyncSequence, мы можем интегрировать его с другими асинхронными операциями в нашем приложении. - Эффективность использования аккумулятора: поскольку функция обеспечивает автоматическую паузу/возобновление обновления местоположения в зависимости от того, движется пользователь или неподвижен, она также способствует увеличению времени автономной работы.
Как использовать CLLocationUpdate
Использование класса CLLocationUpdate для обновления местоположения требует выполнения следующих шагов:
- Импортируйте
CoreLocation. - Затем вызовите статическую фабричную функцию
.liveUpdates(), предоставляемую классом CLLocationUpdate, чтобы получить обновления в виде последовательностиAsyncSequence. Эта последовательность может быть итерирована напрямую с помощьюfor/try/awaitдля получения CLLocationUpdate в замыкании. - Теперь используйте CLLocationUpdate, полученный в замыкании, чтобы получить местоположение, обратившись к его свойству location.
import CoreLocation
func startLocationUpdates() {
// Take location permissions before
Task {
do {
let updates = CLLocationUpdate.liveUpdates()
for try await update in updates {
print ("Current Location is \(update.location)")
// To stop updates break out of the for loop
if update.isStationary {
break
}
}
} catch {
debugPrint("Some Error Occured")
}
}
}
Как это работает за кулисами?
- В новом классе CLLocationUpdate у нас есть статическая функция
.liveUpdates(). Она возвращает последовательность AsyncSequence под названием Updates, которую можно напрямую итерировать с помощью циклаfor/try/await. - Updates при итерации с помощью цикла
for/try/awaitдаетCLLocationUpdate, содержащий местоположение типаCLLocationи булевский флагisStationaryдля управления автоматическими паузами и возобновлениями.
public struct CLLocationUpdate : Sendable {
public let location : CLLocation? // nil if no location is available
public let isStationary : Bool // true if device becomes stationary
}
- Мы также можем передать функции
.liveUpdates()аргумент типаLiveConfiguration, который является перечислением. Он используется в качестве маркера типа активности, на которую вы ориентируетесь при запросе местоположения.
public enum LiveConfiguration {
case default
case automotiveNavigation
case otherNavigation
case fitness
case airborne
}
Добавление фильтра расстояний при обновлении
Мы также можем отфильтровать только те места, которые удовлетворяют нашему минимальному расстоянию. Чтобы добавить эту логику, нам нужно добавить фильтр в нашу функцию .liveUpdates().
private var previousLocation: CLLocation? = nil
private var distanceThreshold: CLLocationDistance = 0.0
...
let locationUpdates = CLLocationUpdate.liveUpdates(.fitness).filter { [weak self] update in
guard let self else { return false }
guard let previousLocation = self.previousLocation else {
self.previousLocation = update.location
return true
}
let distanceMoved = update.location?.distance(from: previousLocation)
if distanceMoved ?? 0.0 >= distanceThreshold || update.isStationary {
self.previousLocation = update.location
return true
}
return false
}
....
Как получать обновления местоположения в фоновом режиме
Мы можем получать обновления местоположения в фоновом режиме двумя способами.
1. Live Activity
- Live Activity отображает актуальную информацию из вашего приложения, позволяя людям сразу же увидеть ход выполнения действия, события или задачи.
- Пока Live Activity остается активной, приложение может получать обновления без дополнительных настроек.
2. CLBackgroundActivitySession
- Многие приложения не имеют Live Activity. В этом случае мы можем использовать
CLBackgroundActivitySession. - Она не только обеспечивает обновление местоположения в фоновом режиме, но и помогает отслеживать такие события, как геозонирование, с помощью
CLMonitor. - Для использования
CLBackgroundActivitySessionнам нужно инстанцировать его объект, чтобы начать новую сессию. - Также необходимо убедиться в том, что мы удерживаем объект, поскольку его удаление автоматически аннулирует сессию, что может привести к прекращению доступа приложения к фоновому получению данных о местоположении.
- После инстанцирования объекта мы присваиваем его любой глобальной переменной, чтобы он не мог быть деаллоцирован даже в случае завершения скоупа.
- Когда мы захотим прекратить обновление местоположения, мы можем просто вызвать
.invalidate()для свойства, в котором мы разместилиCLBackgroundActivitySession.
// CLBackgroundActivitySession in action
import CoreLocation
private var backgroundActivity: CLBackgroundActivitySession?
func startLocationUpdates() {
// Take background location permissions before
Task {
do {
// Assign the CLBackgroundActivitySession to global var
self.backgroundActivity = CLBackgroundActivitySession()
let updates = CLLocationUpdate.liveUpdates()
for try await update in updates {
...
}
} catch {
debugPrint("Some Error Occured")
}
}
}
func stopBackgroundLocation() {
// to stop the background updates
self.backgroundActivity?.invalidate()
}
Жизненный цикл приложения
1. Переход из фонового состояния в приостановленное
- Как уже говорилось, этот новый класс может предоставлять обновления местоположения в фоновом режиме и приостанавливать обновление, когда пользователь неподвижен.
- Когда приложение находится в фоновом режиме, а обновления местоположения не запускаются, оно может перейти из фонового состояния в приостановленное (это также может быть связано с нехваткой ресурсов).
- Интересно то, что класс
CLLLocationUpdateне может оставлять приложение в приостановленном состоянии. - Как только обновления местоположения станут доступны, он отменит приостановку приложения и перейдет обратно в фоновое состояние. А нам не нужно писать никакой код для продолжения обновления местоположения.
2. Что делать, если приложение завершено
CLLocationUpdateможет восстановить приложение, даже если оно завершено и не запущено. Он начнет предоставлять обновления местоположения, как только они станут доступны, и приложение будет перезапущено в фоновом режиме.- В этом случае приложение перейдет из завершенного в работающее в фоновом режиме.
- Но когда приложение будет завершено, нам нужно выполнить несколько шагов, чтобы запустить обновления местоположения.
- Во-первых, нужно вызвать
CLLocationUpdate.liveUpdates(). Также нам нужно воссоздатьCLBackgroundActivitySession. - Когда приложение находится в фоновом режиме и ему нужно продолжать получать обновления местоположения, оно может присоединиться к существующей
CLBackgroundActivitySession. ПересоздавCLBackgroundActivitySession, приложение может подключиться к уже запущенному сеансу, гарантируя, что фоновые обновления местоположения будут поступать без перерыва. - Чтобы приложение могло повторно подключиться к существующей
CLBackgroundActivitySessionпри запуске в фоновом режиме, воссоздание необходимых объектов должно быть помещено в метод, который выполняется во время фонового запуска приложения. Одним из подходящих мест является методdidFinishLaunchingWithOptionsделегата приложения, который вызывается, когда приложение завершает запуск, независимо от того, было ли оно запущеноявно или в фоновом режиме.
Вывод

Демонстрация получения обновлений местоположения с помощью класса CLLocationUpdate
Заключение
Класс CLLocationUpdate, представленный на WWDC 23, это значительный шаг вперед для разработчиков, работающих с данными о местоположении в Swift. Используя современные функции параллелизма, он упрощает процесс получения и управления обновлениями местоположения, что приводит к созданию более чистого, читабельного и эффективного кода. Примите этот новый подход и оптимизируйте свои приложения на основе данных о местоположении в Swift!
-
Аналитика магазинов2 недели назад
Мобильный рынок Ближнего Востока: исследование Bidease и Sensor Tower выявляет драйверы роста
-
Интегрированные среды разработки3 недели назад
Chad: The Brainrot IDE — дикая среда разработки с играми и развлечениями
-
Новости4 недели назад
Видео и подкасты о мобильной разработке 2025.45
-
Новости3 недели назад
Видео и подкасты о мобильной разработке 2025.46




