LNLocationManager.swift 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. //
  2. // LNLocationManager.swift
  3. // Lanu
  4. //
  5. // Created by OneeChan on 2025/12/25.
  6. //
  7. import Foundation
  8. import CoreLocation
  9. import AutoCodable
  10. @AutoCodable
  11. private class LNUserLocation: Codable {
  12. var latitude: CLLocationDegrees = 0
  13. var longitude: CLLocationDegrees = 0
  14. init(latitude: CLLocationDegrees, longitude: CLLocationDegrees) {
  15. self.latitude = latitude
  16. self.longitude = longitude
  17. }
  18. }
  19. class LNLocationManager: NSObject {
  20. static let shared = LNLocationManager()
  21. private let locationManager = CLLocationManager()
  22. private var curLocation: LNUserLocation? = LNUserDefaults[.location] {
  23. didSet {
  24. LNUserDefaults[.location] = curLocation
  25. }
  26. }
  27. private var lastTime: TimeInterval? = LNUserDefaults[.reportLocationTime] {
  28. didSet {
  29. LNUserDefaults[.reportLocationTime] = lastTime
  30. }
  31. }
  32. private var shouldReportLocation: Bool {
  33. guard curLocation != nil, let lastTime else { return true }
  34. return curTime - lastTime > 3 * 60 * 60 // 3 小时内不拉取
  35. }
  36. private override init() {
  37. super.init()
  38. locationManager.delegate = self
  39. locationManager.desiredAccuracy = kCLLocationAccuracyBest // 最高精度
  40. LNEventDeliver.addObserver(self)
  41. }
  42. }
  43. extension LNLocationManager: CLLocationManagerDelegate {
  44. func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
  45. guard let userLocation = locations.last else { return }
  46. guard -userLocation.timestamp.timeIntervalSinceNow < 5 else {
  47. // 只使用5秒内的位置
  48. Log.d("位置过期,忽略")
  49. return
  50. }
  51. guard userLocation.horizontalAccuracy >= 0, userLocation.horizontalAccuracy <= 100 else {
  52. Log.d("位置精度不足(\(userLocation.horizontalAccuracy)米),继续等待")
  53. return
  54. }
  55. manager.stopUpdatingLocation()
  56. curLocation = .init(latitude: userLocation.coordinate.latitude, longitude: userLocation.coordinate.longitude)
  57. lastTime = curTime
  58. uploadLocation(coordinate: userLocation.coordinate)
  59. }
  60. func locationManager(_ manager: CLLocationManager, didFailWithError error: any Error) { }
  61. }
  62. extension LNLocationManager: LNAccountManagerNotify {
  63. func onUserLogin() {
  64. getLocationIfNeed()
  65. }
  66. }
  67. extension LNLocationManager {
  68. private func getLocationIfNeed() {
  69. if shouldReportLocation {
  70. locationManager.requestWhenInUseAuthorization() // 请求使用时的定位权限
  71. locationManager.startUpdatingLocation() // 开始更新位置
  72. }
  73. }
  74. private func uploadLocation(coordinate: CLLocationCoordinate2D) {
  75. LNHttpManager.shared.uploadLocation(
  76. longitude: coordinate.longitude,
  77. latitude: coordinate.latitude
  78. ) { _ in }
  79. }
  80. }