AMapManager.swift 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. //
  2. // AMapManager.swift
  3. // RainbowPlanet
  4. //
  5. // Created by 南鑫林 on 2019/3/27.
  6. // Copyright © 2019 南鑫林. All rights reserved.
  7. //
  8. import UIKit
  9. class AMapManager: NSObject {
  10. private static let _sharedInstance = AMapManager()
  11. private override init() {} // 私有化init方法
  12. typealias LocationModelBlock = (_ locationModel: AMapLocationModel) -> Void
  13. class func shared() -> AMapManager {
  14. return _sharedInstance
  15. }
  16. var locationModel = AMapLocationModel.shared().getLocationModel()
  17. public func initAMap() -> Void {
  18. AMapServices.shared().apiKey = kAMapAppKey
  19. requestLocation(isSoughSingleLocation: true, isAccurateSingleLocation: false) { [weak self] (locationModel) in
  20. self?.locationModel = locationModel
  21. }
  22. }
  23. private lazy var locationManager: AMapLocationManager = {
  24. // 注意: locationManager为该类的属性
  25. let locationManager = AMapLocationManager()
  26. locationManager.locatingWithReGeocode = true
  27. return locationManager
  28. }()
  29. /// 粗单次定位
  30. private func soughSingleLocation() {
  31. // 带逆地理信息的一次定位(返回坐标和地址信息)
  32. locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters
  33. // 定位超时时间,最低2s,此处设置为2s
  34. locationManager.locationTimeout = 2
  35. // 逆地理请求超时时间,最低2s,此处设置为2s
  36. locationManager.reGeocodeTimeout = 2
  37. }
  38. /// 精准单次定位
  39. private func accurateSingleLocation() {
  40. // 带逆地理信息的一次定位(返回坐标和地址信息)
  41. locationManager.desiredAccuracy = kCLLocationAccuracyBest
  42. // 定位超时时间,最低2s,此处设置为10s
  43. locationManager.locationTimeout = 10
  44. // 逆地理请求超时时间,最低2s,此处设置为10s
  45. locationManager.reGeocodeTimeout = 10
  46. locationManager.distanceFilter = 10
  47. }
  48. private func isSoughAccurateSingle(isSoughSingleLocation:Bool = false, isAccurateSingleLocation:Bool = false) {
  49. //粗单次定位
  50. if isSoughSingleLocation {
  51. soughSingleLocation()
  52. }
  53. //精准单次定位
  54. if isAccurateSingleLocation {
  55. soughSingleLocation()
  56. }
  57. }
  58. /// 请求单次定位
  59. ///
  60. /// - Parameters:
  61. /// - isSoughSingleLocation:
  62. /// - isAccurateSingleLocation: 粗单次定位 默认不调用
  63. /// - locationModelBlock: 精准单次定位 默认不调用
  64. public func requestLocation(isSoughSingleLocation:Bool = false, isAccurateSingleLocation:Bool = false, locationModelBlock:@escaping LocationModelBlock) {
  65. //粗单次定位
  66. if isSoughSingleLocation {
  67. soughSingleLocation()
  68. }
  69. //精准单次定位
  70. if isAccurateSingleLocation {
  71. soughSingleLocation()
  72. }
  73. locationManager.requestLocation(withReGeocode: true, completionBlock: {[weak self] (location: CLLocation?, reGeocode: AMapLocationReGeocode?, error: Error?) in
  74. if let error = error {
  75. let error = error as NSError
  76. if error.code == AMapLocationErrorCode.locateFailed.rawValue {
  77. //定位错误:此时location和regeocode没有返回值,不进行annotation的添加
  78. NXLLog("定位错误:{\(error.code) - \(error.localizedDescription)};")
  79. return
  80. } else if error.code == AMapLocationErrorCode.reGeocodeFailed.rawValue
  81. || error.code == AMapLocationErrorCode.timeOut.rawValue
  82. || error.code == AMapLocationErrorCode.cannotFindHost.rawValue
  83. || error.code == AMapLocationErrorCode.badURL.rawValue
  84. || error.code == AMapLocationErrorCode.notConnectedToInternet.rawValue
  85. || error.code == AMapLocationErrorCode.cannotConnectToHost.rawValue {
  86. //逆地理错误:在带逆地理的单次定位中,逆地理过程可能发生错误,此时location有返回值,regeocode无返回值,进行annotation的添加
  87. NXLLog("逆地理错误:{\(error.code) - \(error.localizedDescription)};")
  88. } else {
  89. //没有错误:location有返回值,regeocode是否有返回值取决于是否进行逆地理操作,进行annotation的添加
  90. }
  91. }
  92. self?.locationModel = self?.savelocationModel(location: location, reGeocode: reGeocode)
  93. locationModelBlock(self?.locationModel ?? AMapLocationModel.shared().getLocationModel()!)
  94. })
  95. }
  96. /// 后台定位
  97. public func backgroundLocation() {
  98. locationManager.delegate = self
  99. locationManager.distanceFilter = 100
  100. //iOS 9(不包含iOS 9) 之前设置允许后台定位参数,保持不会被系统挂起
  101. locationManager.pausesLocationUpdatesAutomatically = false
  102. //iOS 9(包含iOS 9)之后新特性:将允许出现这种场景,同一app中多个locationmanager:一些只能在前台定位,另一些可在后台定位,并可随时禁止其后台定位。
  103. if UIDevice.current.systemVersion._bridgeToObjectiveC().doubleValue >= 9.0 {
  104. locationManager.pausesLocationUpdatesAutomatically = true
  105. }
  106. //开始持续定位
  107. locationManager.startUpdatingLocation()
  108. }
  109. /// 持续定位
  110. public func continuedLocation() {
  111. locationManager.delegate = self
  112. locationManager.distanceFilter = 100
  113. //iOS 9(包含iOS 9)之后新特性:将允许出现这种场景,同一app中多个locationmanager:一些只能在前台定位,另一些可在后台定位,并可随时禁止其后台定位。
  114. if UIDevice.current.systemVersion._bridgeToObjectiveC().doubleValue >= 9.0 {
  115. locationManager.pausesLocationUpdatesAutomatically = true
  116. }
  117. //开始持续定位
  118. locationManager.startUpdatingLocation()
  119. }
  120. /// 停止定位
  121. public func stopUpdatingLocation() {
  122. locationManager.stopUpdatingLocation()
  123. }
  124. public func savelocationModel(location: CLLocation!, reGeocode: AMapLocationReGeocode?) -> AMapLocationModel {
  125. if let location = location {
  126. NXLLog("location:\(location)")
  127. locationModel?.longitude = String(describing: location.coordinate.longitude)
  128. locationModel?.latitude = String(describing: location.coordinate.latitude)
  129. }
  130. if let reGeocode = reGeocode {
  131. NXLLog("reGeocode:\(reGeocode)")
  132. /// 国家
  133. locationModel?.country = reGeocode.country ?? ""
  134. /// 省份
  135. locationModel?.province = reGeocode.province ?? ""
  136. /// 市
  137. locationModel?.city = reGeocode.city ?? ""
  138. /// 区/县
  139. locationModel?.district = reGeocode.district ?? ""
  140. /// 街道
  141. locationModel?.street = reGeocode.street ?? ""
  142. /// 详细描述
  143. locationModel?.poiName = reGeocode.poiName ?? ""
  144. /// AOIName
  145. locationModel?.aoiName = reGeocode.aoiName ?? ""
  146. /// 编号
  147. locationModel?.number = reGeocode.number ?? ""
  148. /// 城市Code
  149. locationModel?.citycode = reGeocode.citycode ?? ""
  150. /// adcode
  151. locationModel?.adcode = reGeocode.adcode ?? ""
  152. /// 地址格式化
  153. locationModel?.formattedAddress = reGeocode.formattedAddress ?? ""
  154. }
  155. AMapLocationModel.shared().setLocationModel(locationModel: locationModel!)
  156. return locationModel!
  157. }
  158. }
  159. // MARK: - 持续定位/后台定位
  160. extension AMapManager: AMapLocationManagerDelegate {
  161. func amapLocationManager(_ manager: AMapLocationManager!, didUpdate location: CLLocation!, reGeocode: AMapLocationReGeocode?) {
  162. NXLLog("location:{lat:\(location.coordinate.latitude); lon:\(location.coordinate.longitude); accuracy:\(location.horizontalAccuracy);};");
  163. locationModel = savelocationModel(location: location, reGeocode: reGeocode)
  164. }
  165. }