Site icon AppTractor

Оптимизируем обновление местоположения с помощью CLLocationUpdate в Swift

Screenshot

На WWDC 23 Apple значительно улучшила процесс обновления местоположения, представив класс CLLocationUpdate. Этот новый класс использует возможности современного Swift Concurrency, упрощая получение и управление данными о местоположении в ваших приложениях.

Что нового?

Почему стоит использовать CLLocationUpdate

Как использовать CLLocationUpdate

Использование класса CLLocationUpdate для обновления местоположения требует выполнения следующих шагов:

  1. Импортируйте CoreLocation.
  2. Затем вызовите статическую фабричную функцию .liveUpdates(), предоставляемую классом CLLocationUpdate, чтобы получить обновления в виде последовательности AsyncSequence. Эта последовательность может быть итерирована напрямую с помощью for/try/await для получения CLLocationUpdate в замыкании.
  3. Теперь используйте 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")
        }
    }
}

Как это работает за кулисами?

  1. В новом классе CLLocationUpdate у нас есть статическая функция .liveUpdates() . Она возвращает последовательность AsyncSequence под названием Updates, которую можно напрямую итерировать с помощью цикла for/try/await.
  2. 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
}
  1. Мы также можем передать функции .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

2. 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. Переход из фонового состояния в приостановленное

2. Что делать, если приложение завершено

Вывод

Демонстрация получения обновлений местоположения с помощью класса CLLocationUpdate

Заключение

Класс CLLocationUpdate, представленный на WWDC 23, это значительный шаг вперед для разработчиков, работающих с данными о местоположении в Swift. Используя современные функции параллелизма, он упрощает процесс получения и управления обновлениями местоположения, что приводит к созданию более чистого, читабельного и эффективного кода. Примите этот новый подход и оптимизируйте свои приложения на основе данных о местоположении в Swift!

Exit mobile version