81 lines
2.2 KiB
Swift
81 lines
2.2 KiB
Swift
//
|
|
// LocationService.swift
|
|
// AutoCatCore
|
|
//
|
|
// Created by Selim Mustafaev on 31.07.2024.
|
|
// Copyright © 2024 Selim Mustafaev. All rights reserved.
|
|
//
|
|
|
|
import CoreLocation
|
|
import SwiftLocation
|
|
|
|
@MainActor
|
|
public final class LocationService {
|
|
|
|
@Service var geocoder: GeocoderProtocol
|
|
@Service var locationManager: SwiftLocationProtocol
|
|
|
|
private var eventTask: Task<VehicleEventDto,Error>?
|
|
|
|
public init() {
|
|
|
|
}
|
|
|
|
private func checkPermissions() async throws {
|
|
|
|
switch locationManager.authorizationStatus {
|
|
case .authorizedWhenInUse, .authorizedAlways:
|
|
break
|
|
case .notDetermined:
|
|
_ = try await locationManager.requestPermission(.always)
|
|
try await checkPermissions()
|
|
case .denied:
|
|
throw CLError(.denied)
|
|
default:
|
|
throw LocationError.permission
|
|
}
|
|
}
|
|
|
|
private func requestLocation() async throws -> VehicleEventDto {
|
|
try await checkPermissions()
|
|
let locationEvent = try await locationManager.requestLocation(accuracy: nil, timeout: 20)
|
|
|
|
guard let coordinate = locationEvent.location?.coordinate else {
|
|
throw LocationError.generic
|
|
}
|
|
|
|
return VehicleEventDto(lat: coordinate.latitude, lon: coordinate.longitude)
|
|
}
|
|
}
|
|
|
|
extension LocationService: LocationServiceProtocol {
|
|
|
|
public func getAddressForLocation(latitude: Double, longitude: Double) async throws -> String {
|
|
|
|
let location = CLLocation(latitude: latitude, longitude: longitude)
|
|
let placemarks = try await geocoder.reverseGeocodeLocation(location)
|
|
|
|
if let name = placemarks.first?.name {
|
|
return name
|
|
} else {
|
|
throw LocationError.reverseGeocode
|
|
}
|
|
}
|
|
|
|
@discardableResult
|
|
public func requestCurrentLocation() async throws -> VehicleEventDto {
|
|
|
|
if let eventTask {
|
|
return try await eventTask.value
|
|
} else {
|
|
let task = Task {
|
|
let location = try await requestLocation()
|
|
eventTask = nil
|
|
return location
|
|
}
|
|
eventTask = task
|
|
return try await task.value
|
|
}
|
|
}
|
|
}
|