// // IHHotelMapView.swift // Inhealth // // Created by weclouds on 2019/12/13. // Copyright © 2019 weclouds. All rights reserved. // import UIKit import MapKit import CoreLocation let kNotificationIHHotelMapViewGetAllHotelData = "kNotificationIHHotelMapViewGetAllHotelData" protocol IHHotelMapViewDelegate : NSObjectProtocol { func getMapViewRegin(_ lat_low:String,long_low:String,lat_high:String,long_high:String) func didSelectCalloutView(_ annotation: IHAnotation) func locationManagerDidFailWithError() } class IHHotelMapView: UIView { fileprivate var isStartLocation : Bool? = true var selectedCoordinate:CLLocationCoordinate2D?{ didSet{ //处理事件 if let coordinate = self.selectedCoordinate { isStartLocation = false let location = CLLocation(latitude: coordinate.latitude, longitude: coordinate.latitude) centerMapOnLocation(location: location) }else{ isStartLocation = true } } } var AllHotelData:[HotelMapData]? //所有的酒店数据 var fillterResult: [HotelMapData]? //过滤的结果 { didSet{ } } var searchFiled:UITextField? var showAnonations:[IHAnotation]? = [IHAnotation]() var receviceAnonations: [IHAnotation]? = [IHAnotation]() lazy var resultView: IHMapResultView = {//搜索结果view let resultView = IHMapResultView() resultView.frame = CGRect(x: 0, y: 0, width: KSCREENWIDTH, height: KSCREENHEIGHT - KNavBarHeight - 50) resultView.isHidden = true return resultView }() weak var delegate: IHHotelMapViewDelegate? private var isOnce = true var mapDatas :[HotelMapData]?{ didSet{ addAnnotationsToMapView() } } public var mapView : MKMapView! let locationManager = CLLocationManager() lazy var locationBtn: UIButton = { let locationBtn = UIButton(type: .custom) locationBtn.setImage(UIImage(named: "定位当前位置"), for: .normal) locationBtn.backgroundColor = .white locationBtn.addTarget(self, action: #selector(locationAction), for: .touchUpInside) return locationBtn }() lazy var callOut: IHCallView = { let callOut = Bundle.main.loadNibNamed("IHCallView", owner: nil, options: nil)?.last as! IHCallView /// callOut.backgroundColor = UIColor.red callOut.isHidden = true return callOut }() override init(frame: CGRect) { super.init(frame: frame) NotificationCenter.default.addObserver(self, selector: #selector(notifyAllHotelData(_:)), name: NSNotification.Name(kNotificationIHHotelMapViewGetAllHotelData), object: nil) createMapView() } deinit { log.debug("IHHotelMapView销毁") NotificationCenter.default.removeObserver(self) } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } @objc func notifyAllHotelData(_ notify:Notification) { self.AllHotelData = notify.object as? [HotelMapData] self.resultView.mapHotelArr = AllHotelData } override func layoutSubviews() { super.layoutSubviews() mapView.snp.makeConstraints { (make) in make.right.left.top.bottom.equalToSuperview() } locationBtn.snp.makeConstraints { (make) in make.right.equalToSuperview().offset(-12) make.bottom.equalToSuperview().offset(-167) make.width.height.equalTo(37) } callOut.snp.makeConstraints({ (make) in make.bottom.equalToSuperview().offset(-34) make.left.equalTo(0) make.right.equalTo(0) make.height.equalTo(140 + 50) }) } @objc func locationAction() { isStartLocation = true //重新开始定位 startLocation() } func createMapView() { mapView = MKMapView() mapView.delegate = self addSubview(mapView) backgroundColor = .blue //设置地图类型 mapView.mapType = .standard mapView.showsUserLocation = true mapView.userTrackingMode = .follow locationManager.delegate = self locationManager.requestWhenInUseAuthorization() locationManager.requestAlwaysAuthorization() locationManager.desiredAccuracy = kCLLocationAccuracyBest //开始update user位置 startLocation() mapView.userTrackingMode = .none //不跟随移动 //addAnnotationsToMapView() addSubview(locationBtn) addSubview(callOut) locationBtn.layer.masksToBounds = true locationBtn.layer.cornerRadius = 9 addSubview(resultView) let searchView = UIView(frame: CGRect(x: 20, y: 15, width: KSCREENWIDTH - 40, height: 38)) searchView.backgroundColor = UIColor(hexString: "ffffff") searchView.layer.cornerRadius = 19 searchView.layer.masksToBounds = true self.addSubview(searchView) let searchfiled = UITextField(frame: CGRect(x: 15 , y: 5, width: KSCREENWIDTH - 40 - 30 - 20, height: 30)) searchfiled.delegate = self searchfiled.placeholder = "输入关键字进行查找..." searchfiled.font = UIFont(name: PingFangSC_Medium, size: 12) searchfiled.textColor = UIColor(hexString: "333333") searchfiled.returnKeyType = .search searchfiled.clearButtonMode = .always searchView.addSubview(searchfiled) self.searchFiled = searchfiled let searchIcon = UIImageView(image: UIImage(named: "搜索")) searchView.addSubview(searchIcon) searchIcon.snp.makeConstraints { (make) in make.centerY.equalToSuperview() make.right.equalToSuperview().offset(-10) make.width.height.equalTo(15) } resultView.callback = {[unowned self] (hotel) in self.mapSelectedHotel(hotel) } } //选择酒店回调 func mapSelectedHotel(_ hotel :HotelMapData) { if let latitude = hotel.latitude,let longitude = hotel.longitude { self.resultView.isHidden = true let lat = Double(latitude) let lng = Double(longitude) // let coordinte = CLLocationCoordinate2D(latitude: lat!, longitude: lng!) let location = CLLocation(latitude: lat!, longitude: lng!) centerMapOnLocation(location: location) self.endEditing(true) //收起键盘 self.searchFiled?.text = "" //显示当前气泡 delay(1) { for ano in self.showAnonations! { if ano.id == hotel.id { self.mapView.selectAnnotation(ano, animated: true) self.callOut.hotelData = hotel self.callOut.isHidden = false } } } } } func startLocation() { print("进入普通定位态"); locationManager.startUpdatingLocation() mapView.showsUserLocation = false//先关闭显示的定位图层 mapView.showsUserLocation = true//显示定位图层 } func stopLocation() { locationManager.stopUpdatingLocation() mapView.showsUserLocation = false } //显示周围1000米的区域 let regionRadius: CLLocationDistance = 1000 func centerMapOnLocation(location: CLLocation) { let coordinateRegion = MKCoordinateRegion(center: location.coordinate, latitudinalMeters: regionRadius, longitudinalMeters: regionRadius) mapView.setRegion(coordinateRegion, animated: true) } func addAnnotationsToMapView() { if showAnonations!.count > 0 && showAnonations != nil { self.mapView.removeAnnotations(showAnonations!) } if let mapDatas = mapDatas { if mapDatas.count > 0 {//如果有值的时候, for map in mapDatas { if let lat = map.latitude ,let lng = map.longitude,let id = map.id,let name = map.name{ let latitude = Double(lat) let longitude = Double(lng) let location = CLLocationCoordinate2DMake(latitude!, longitude!) let annotation = IHAnotation(coordinate: location, icon: UIImage(named: "地图未选中点"),id:id,name: name ,hotelData:map ) receviceAnonations?.append(annotation) } } } } showAnonations = receviceAnonations self.mapView.addAnnotations(showAnonations!) } } extension IHHotelMapView:MKMapViewDelegate{ //地图缩放完毕触发 func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool) { log.debug("地图缩放完毕触法") if isOnce == false{ return } isOnce = false let point1 = CGPoint(x: 0, y: 0) let point2 = CGPoint(x: mapView.width, y: mapView.height) //屏幕坐标转地图坐标 let coor1 = mapView.convert(point1, toCoordinateFrom: mapView) let coor2 = mapView.convert(point2, toCoordinateFrom: mapView) //获取坐标 let lat_high = String(coor1.latitude) let lng_low = String(coor1.longitude) let lat_low = String(coor2.latitude) let lng_high = String(coor2.longitude) if let delegate = self.delegate { delegate.getMapViewRegin(lat_low, long_low: lng_low, lat_high: lat_high, long_high: lng_high) } IHHotelMapService.share.getHotelMapData("-180", lng_high: "180", lat_low: "-90", lat_high: "90", requestSuccess: { (data) in self.mapDatas = data }) { } } func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? { if annotation.isKind(of: IHAnotation.self) { let annotationIH = annotation as! IHAnotation let key = "AnnotationIdentifier" //重用机制 var view = self.mapView.dequeueReusableAnnotationView(withIdentifier: key) as? IHAnotationView if view == nil { view = IHAnotationView(annotation: annotation, reuseIdentifier: key) } //设置大头针数据 view?.annotation = annotation view?.image = annotationIH.icon return view } return nil } // mapView 跟tableView的结构不一样,有顺序,map只可以把数据绑定到Anotation中 func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) { if view.isKind(of: IHAnotationView.self) == false { return } view.image = UIImage(named: "地图选中点") let annotion = view.annotation as? IHAnotation //callOut.backgroundColor = .random callOut.isHidden = false callOut.hotelName = annotion?.name callOut.hotelData = annotion?.hotelData callOut.closeCallback = { // 关闭callOut [unowned self] in self.callOut.isHidden = true view.image = UIImage(named: "地图未选中点") } //选中callout callOut.didSelectedCallout = { [unowned self] in self.delegate?.didSelectCalloutView(annotion!) } } func mapView(_ mapView: MKMapView, didDeselect view: MKAnnotationView) { if view.isKind(of: IHAnotationView.self) == false { return } callOut.isHidden = true view.image = UIImage(named: "地图未选中点") } } extension IHHotelMapView:CLLocationManagerDelegate{ func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) { manager.stopUpdatingLocation() if let delegate = self.delegate { delegate.locationManagerDidFailWithError() } } func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { let userLocation : CLLocation = locations.first! //最新位置 // // let coordinate = userLocation.coordinate // let _lat = coordinate.latitude // let _lng = coordinate.longitude // //火星坐标系 // let (lat, lng) = LocationTransform.wgs2gcj(wgsLat: _lat, wgsLng: _lng) // let _location : = CLLocation(latitude: lat, longitude: lng) if isStartLocation == true { centerMapOnLocation(location: userLocation) } manager.stopUpdatingLocation() } } extension IHHotelMapView : UITextFieldDelegate{ func textFieldShouldReturn(_ textField: UITextField) -> Bool { self.endEditing(true) return true } func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { let currentText = searchFiled?.text ?? "" let newText = (currentText as NSString).replacingCharacters(in: range, with: string) log.debug("搜索内容 - \(newText) -- \(currentText)") if #available(iOS 13, *) { //iOS 13 九空格切换有问题 }else{ filterContent(for: newText) } return true } func textFieldShouldClear(_ textField: UITextField) -> Bool { log.debug("点击了清楚按钮 ") return true } //iOS 13 新增api func textFieldDidChangeSelection(_ textField: UITextField) { //iOS 13之后使用 if #available(iOS 13, *){ let currentText = searchFiled?.text ?? "" filterContent(for: currentText) } } ///过滤 func filterContent(for searchText:String) { resultView.isHidden = false // guard let hotellist = AllHotelData else { return } let hotelName = searchText var fillterHotelNS : [HotelMapData]? if hotelName == "" || self.AllHotelData == nil || self.AllHotelData?.count == 0 { //没有输入则为传入的内容 fillterHotelNS = AllHotelData }else{ fillterHotelNS = (AllHotelData?.filter({ (hotel) -> Bool in //全部转为小写 在比较 let name = hotel.name!.lowercased() let search = searchText.lowercased() return name.contains(search) == true // return province.name!.contains(searchText) == true }))! } fillterResult = fillterHotelNS //23log.debug(fillterResult) NotificationCenter.default.post(name: NSNotification.Name(rawValue: kNotifactionIHMapResultViewReloadData), object: fillterHotelNS) } }