IHHotelMapView.swift 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437
  1. //
  2. // IHHotelMapView.swift
  3. // Inhealth
  4. //
  5. // Created by weclouds on 2019/12/13.
  6. // Copyright © 2019 weclouds. All rights reserved.
  7. //
  8. import UIKit
  9. import MapKit
  10. import CoreLocation
  11. let kNotificationIHHotelMapViewGetAllHotelData = "kNotificationIHHotelMapViewGetAllHotelData"
  12. protocol IHHotelMapViewDelegate : NSObjectProtocol {
  13. func getMapViewRegin(_ lat_low:String,long_low:String,lat_high:String,long_high:String)
  14. func didSelectCalloutView(_ annotation: IHAnotation)
  15. func locationManagerDidFailWithError()
  16. }
  17. class IHHotelMapView: UIView {
  18. fileprivate var isStartLocation : Bool? = true
  19. var selectedCoordinate:CLLocationCoordinate2D?{
  20. didSet{
  21. //处理事件
  22. if let coordinate = self.selectedCoordinate {
  23. isStartLocation = false
  24. let location = CLLocation(latitude: coordinate.latitude, longitude: coordinate.latitude)
  25. centerMapOnLocation(location: location)
  26. }else{
  27. isStartLocation = true
  28. }
  29. }
  30. }
  31. var AllHotelData:[HotelMapData]? //所有的酒店数据
  32. var fillterResult: [HotelMapData]? //过滤的结果
  33. {
  34. didSet{
  35. }
  36. }
  37. var searchFiled:UITextField?
  38. var showAnonations:[IHAnotation]? = [IHAnotation]()
  39. var receviceAnonations: [IHAnotation]? = [IHAnotation]()
  40. lazy var resultView: IHMapResultView = {//搜索结果view
  41. let resultView = IHMapResultView()
  42. resultView.frame = CGRect(x: 0, y: 0, width: KSCREENWIDTH, height: KSCREENHEIGHT - KNavBarHeight - 50)
  43. resultView.isHidden = true
  44. return resultView
  45. }()
  46. weak var delegate: IHHotelMapViewDelegate?
  47. private var isOnce = true
  48. var mapDatas :[HotelMapData]?{
  49. didSet{
  50. addAnnotationsToMapView()
  51. }
  52. }
  53. public var mapView : MKMapView!
  54. let locationManager = CLLocationManager()
  55. lazy var locationBtn: UIButton = {
  56. let locationBtn = UIButton(type: .custom)
  57. locationBtn.setImage(UIImage(named: "定位当前位置"), for: .normal)
  58. locationBtn.backgroundColor = .white
  59. locationBtn.addTarget(self, action: #selector(locationAction), for: .touchUpInside)
  60. return locationBtn
  61. }()
  62. lazy var callOut: IHCallView = {
  63. let callOut = Bundle.main.loadNibNamed("IHCallView", owner: nil, options: nil)?.last as! IHCallView
  64. /// callOut.backgroundColor = UIColor.red
  65. callOut.isHidden = true
  66. return callOut
  67. }()
  68. override init(frame: CGRect) {
  69. super.init(frame: frame)
  70. NotificationCenter.default.addObserver(self, selector: #selector(notifyAllHotelData(_:)), name: NSNotification.Name(kNotificationIHHotelMapViewGetAllHotelData), object: nil)
  71. createMapView()
  72. }
  73. deinit {
  74. log.debug("IHHotelMapView销毁")
  75. NotificationCenter.default.removeObserver(self)
  76. }
  77. required init?(coder: NSCoder) {
  78. fatalError("init(coder:) has not been implemented")
  79. }
  80. @objc func notifyAllHotelData(_ notify:Notification) {
  81. self.AllHotelData = notify.object as? [HotelMapData]
  82. self.resultView.mapHotelArr = AllHotelData
  83. }
  84. override func layoutSubviews() {
  85. super.layoutSubviews()
  86. mapView.snp.makeConstraints { (make) in
  87. make.right.left.top.bottom.equalToSuperview()
  88. }
  89. locationBtn.snp.makeConstraints { (make) in
  90. make.right.equalToSuperview().offset(-12)
  91. make.bottom.equalToSuperview().offset(-167)
  92. make.width.height.equalTo(37)
  93. }
  94. callOut.snp.makeConstraints({ (make) in
  95. make.bottom.equalToSuperview().offset(-34)
  96. make.left.equalTo(0)
  97. make.right.equalTo(0)
  98. make.height.equalTo(140 + 50)
  99. })
  100. }
  101. @objc func locationAction() {
  102. isStartLocation = true
  103. //重新开始定位
  104. startLocation()
  105. }
  106. func createMapView() {
  107. mapView = MKMapView()
  108. mapView.delegate = self
  109. addSubview(mapView)
  110. backgroundColor = .blue
  111. //设置地图类型
  112. mapView.mapType = .standard
  113. mapView.showsUserLocation = true
  114. mapView.userTrackingMode = .follow
  115. locationManager.delegate = self
  116. locationManager.requestWhenInUseAuthorization()
  117. locationManager.requestAlwaysAuthorization()
  118. locationManager.desiredAccuracy = kCLLocationAccuracyBest
  119. //开始update user位置
  120. startLocation()
  121. mapView.userTrackingMode = .none //不跟随移动
  122. //addAnnotationsToMapView()
  123. addSubview(locationBtn)
  124. addSubview(callOut)
  125. locationBtn.layer.masksToBounds = true
  126. locationBtn.layer.cornerRadius = 9
  127. addSubview(resultView)
  128. let searchView = UIView(frame: CGRect(x: 20, y: 15, width: KSCREENWIDTH - 40, height: 38))
  129. searchView.backgroundColor = UIColor(hexString: "ffffff")
  130. searchView.layer.cornerRadius = 19
  131. searchView.layer.masksToBounds = true
  132. self.addSubview(searchView)
  133. let searchfiled = UITextField(frame: CGRect(x: 15 , y: 5, width: KSCREENWIDTH - 40 - 30 - 20, height: 30))
  134. searchfiled.delegate = self
  135. searchfiled.placeholder = "输入关键字进行查找..."
  136. searchfiled.font = UIFont(name: PingFangSC_Medium, size: 12)
  137. searchfiled.textColor = UIColor(hexString: "333333")
  138. searchfiled.returnKeyType = .search
  139. searchfiled.clearButtonMode = .always
  140. searchView.addSubview(searchfiled)
  141. self.searchFiled = searchfiled
  142. let searchIcon = UIImageView(image: UIImage(named: "搜索"))
  143. searchView.addSubview(searchIcon)
  144. searchIcon.snp.makeConstraints { (make) in
  145. make.centerY.equalToSuperview()
  146. make.right.equalToSuperview().offset(-10)
  147. make.width.height.equalTo(15)
  148. }
  149. resultView.callback = {[unowned self] (hotel) in
  150. self.mapSelectedHotel(hotel)
  151. }
  152. }
  153. //选择酒店回调
  154. func mapSelectedHotel(_ hotel :HotelMapData) {
  155. if let latitude = hotel.latitude,let longitude = hotel.longitude {
  156. self.resultView.isHidden = true
  157. let lat = Double(latitude)
  158. let lng = Double(longitude)
  159. // let coordinte = CLLocationCoordinate2D(latitude: lat!, longitude: lng!)
  160. let location = CLLocation(latitude: lat!, longitude: lng!)
  161. centerMapOnLocation(location: location)
  162. self.endEditing(true) //收起键盘
  163. self.searchFiled?.text = ""
  164. //显示当前气泡
  165. delay(1) {
  166. for ano in self.showAnonations! {
  167. if ano.id == hotel.id {
  168. self.mapView.selectAnnotation(ano, animated: true)
  169. self.callOut.hotelData = hotel
  170. self.callOut.isHidden = false
  171. }
  172. }
  173. }
  174. }
  175. }
  176. func startLocation() {
  177. print("进入普通定位态");
  178. locationManager.startUpdatingLocation()
  179. mapView.showsUserLocation = false//先关闭显示的定位图层
  180. mapView.showsUserLocation = true//显示定位图层
  181. }
  182. func stopLocation() {
  183. locationManager.stopUpdatingLocation()
  184. mapView.showsUserLocation = false
  185. }
  186. //显示周围1000米的区域
  187. let regionRadius: CLLocationDistance = 1000
  188. func centerMapOnLocation(location: CLLocation) {
  189. let coordinateRegion = MKCoordinateRegion(center: location.coordinate,
  190. latitudinalMeters: regionRadius, longitudinalMeters: regionRadius)
  191. mapView.setRegion(coordinateRegion, animated: true)
  192. }
  193. func addAnnotationsToMapView() {
  194. if showAnonations!.count > 0 && showAnonations != nil {
  195. self.mapView.removeAnnotations(showAnonations!)
  196. }
  197. if let mapDatas = mapDatas {
  198. if mapDatas.count > 0 {//如果有值的时候,
  199. for map in mapDatas {
  200. if let lat = map.latitude ,let lng = map.longitude,let id = map.id,let name = map.name{
  201. let latitude = Double(lat)
  202. let longitude = Double(lng)
  203. let location = CLLocationCoordinate2DMake(latitude!, longitude!)
  204. let annotation = IHAnotation(coordinate: location, icon: UIImage(named: "地图未选中点"),id:id,name: name ,hotelData:map )
  205. receviceAnonations?.append(annotation)
  206. }
  207. }
  208. }
  209. }
  210. showAnonations = receviceAnonations
  211. self.mapView.addAnnotations(showAnonations!)
  212. }
  213. }
  214. extension IHHotelMapView:MKMapViewDelegate{
  215. //地图缩放完毕触发
  216. func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
  217. log.debug("地图缩放完毕触法")
  218. if isOnce == false{
  219. return
  220. }
  221. isOnce = false
  222. let point1 = CGPoint(x: 0, y: 0)
  223. let point2 = CGPoint(x: mapView.width, y: mapView.height)
  224. //屏幕坐标转地图坐标
  225. let coor1 = mapView.convert(point1, toCoordinateFrom: mapView)
  226. let coor2 = mapView.convert(point2, toCoordinateFrom: mapView)
  227. //获取坐标
  228. let lat_high = String(coor1.latitude)
  229. let lng_low = String(coor1.longitude)
  230. let lat_low = String(coor2.latitude)
  231. let lng_high = String(coor2.longitude)
  232. if let delegate = self.delegate {
  233. delegate.getMapViewRegin(lat_low, long_low: lng_low, lat_high: lat_high, long_high: lng_high)
  234. }
  235. IHHotelMapService.share.getHotelMapData("-180", lng_high: "180", lat_low: "-90", lat_high: "90", requestSuccess: { (data) in
  236. self.mapDatas = data
  237. }) {
  238. }
  239. }
  240. func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
  241. if annotation.isKind(of: IHAnotation.self) {
  242. let annotationIH = annotation as! IHAnotation
  243. let key = "AnnotationIdentifier"
  244. //重用机制
  245. var view = self.mapView.dequeueReusableAnnotationView(withIdentifier: key) as? IHAnotationView
  246. if view == nil {
  247. view = IHAnotationView(annotation: annotation, reuseIdentifier: key)
  248. }
  249. //设置大头针数据
  250. view?.annotation = annotation
  251. view?.image = annotationIH.icon
  252. return view
  253. }
  254. return nil
  255. }
  256. // mapView 跟tableView的结构不一样,有顺序,map只可以把数据绑定到Anotation中
  257. func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
  258. if view.isKind(of: IHAnotationView.self) == false {
  259. return
  260. }
  261. view.image = UIImage(named: "地图选中点")
  262. let annotion = view.annotation as? IHAnotation
  263. //callOut.backgroundColor = .random
  264. callOut.isHidden = false
  265. callOut.hotelName = annotion?.name
  266. callOut.hotelData = annotion?.hotelData
  267. callOut.closeCallback = { // 关闭callOut
  268. [unowned self] in
  269. self.callOut.isHidden = true
  270. view.image = UIImage(named: "地图未选中点")
  271. }
  272. //选中callout
  273. callOut.didSelectedCallout = { [unowned self] in
  274. self.delegate?.didSelectCalloutView(annotion!)
  275. }
  276. }
  277. func mapView(_ mapView: MKMapView, didDeselect view: MKAnnotationView) {
  278. if view.isKind(of: IHAnotationView.self) == false {
  279. return
  280. }
  281. callOut.isHidden = true
  282. view.image = UIImage(named: "地图未选中点")
  283. }
  284. }
  285. extension IHHotelMapView:CLLocationManagerDelegate{
  286. func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
  287. manager.stopUpdatingLocation()
  288. if let delegate = self.delegate {
  289. delegate.locationManagerDidFailWithError()
  290. }
  291. }
  292. func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
  293. let userLocation : CLLocation = locations.first! //最新位置
  294. //
  295. // let coordinate = userLocation.coordinate
  296. // let _lat = coordinate.latitude
  297. // let _lng = coordinate.longitude
  298. // //火星坐标系
  299. // let (lat, lng) = LocationTransform.wgs2gcj(wgsLat: _lat, wgsLng: _lng)
  300. // let _location : = CLLocation(latitude: lat, longitude: lng)
  301. if isStartLocation == true {
  302. centerMapOnLocation(location: userLocation)
  303. }
  304. manager.stopUpdatingLocation()
  305. }
  306. }
  307. extension IHHotelMapView : UITextFieldDelegate{
  308. func textFieldShouldReturn(_ textField: UITextField) -> Bool {
  309. self.endEditing(true)
  310. return true
  311. }
  312. func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
  313. let currentText = searchFiled?.text ?? ""
  314. let newText = (currentText as NSString).replacingCharacters(in: range, with: string)
  315. log.debug("搜索内容 - \(newText) -- \(currentText)")
  316. if #available(iOS 13, *) {
  317. //iOS 13 九空格切换有问题
  318. }else{
  319. filterContent(for: newText)
  320. }
  321. return true
  322. }
  323. func textFieldShouldClear(_ textField: UITextField) -> Bool {
  324. log.debug("点击了清楚按钮 ")
  325. return true
  326. }
  327. //iOS 13 新增api
  328. func textFieldDidChangeSelection(_ textField: UITextField) {
  329. //iOS 13之后使用
  330. if #available(iOS 13, *){
  331. let currentText = searchFiled?.text ?? ""
  332. filterContent(for: currentText)
  333. }
  334. }
  335. ///过滤
  336. func filterContent(for searchText:String) {
  337. resultView.isHidden = false
  338. // guard let hotellist = AllHotelData else { return }
  339. let hotelName = searchText
  340. var fillterHotelNS : [HotelMapData]?
  341. if hotelName == "" || self.AllHotelData == nil || self.AllHotelData?.count == 0 { //没有输入则为传入的内容
  342. fillterHotelNS = AllHotelData
  343. }else{
  344. fillterHotelNS = (AllHotelData?.filter({ (hotel) -> Bool in
  345. //全部转为小写 在比较
  346. let name = hotel.name!.lowercased()
  347. let search = searchText.lowercased()
  348. return name.contains(search) == true
  349. // return province.name!.contains(searchText) == true
  350. }))!
  351. }
  352. fillterResult = fillterHotelNS
  353. //23log.debug(fillterResult)
  354. NotificationCenter.default.post(name: NSNotification.Name(rawValue: kNotifactionIHMapResultViewReloadData), object: fillterHotelNS)
  355. }
  356. }