-
[ios - Swift] MapView 사용하기 (MKMapView 2 / 2)ios 2020. 12. 23. 11:01
이번 글에서는 지난 글에서 얘기한 것과 같이 지역 내 검색 및 좌표에 대한 정보를 추출하는 방법을 알아보도록 하겠습니다.
위 gif를 살펴보면 맵 뷰의 현재 위치, 중앙 위치의 주소, 주변 가게들이 나오는 것을 확인할 수 있습니다.
해당 기능을 사용할 수 있도록 하나씩 작성해 보도록 하겠습니다.
1. 내 위치 찾기
@IBAction func changeValue(_ sender: UISegmentedControl) { // "현재 위치" 선택 - 현재 위치 표시 if sender.selectedSegmentIndex == 0 { self.mainTitle.text = "" self.subTitle.text = "" // 사용자의 현재 위치 locationManager.startUpdatingLocation() } else if sender.selectedSegmentIndex == 1 { setAnnotation(latitudeValue: 37.5207945, longitudeValue: 127.0204729, delta: 0.01, title: "가로수길 서비스 센터", subtitle: "서울 강남구 가로수길 43") self.mainTitle.text = "보고 계신 위치" self.subTitle.text = "가로수길 서비스 센터" } }
SegmentedControl Index 가 0 일 경우 현 위치 업데이트를 실행하도록 합니다.
extension ViewController: CLLocationManagerDelegate { func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { let pLocation = locations.last moveLocation(latitudeValue: (pLocation?.coordinate.latitude)!, longtudeValue: (pLocation?.coordinate.longitude)!, delta: 0.01) CLGeocoder().reverseGeocodeLocation(pLocation!, completionHandler: { (placemarks, error) -> Void in if let pm: CLPlacemark = placemarks?.first { let address: String = "\(pm.locality ?? "") \(pm.name ?? "")" self.mainTitle.text = "내 위치" self.subTitle.text = address } }) locationManager.stopUpdatingLocation() } }
CLLocationManagerDelegate에서 위치 정보 업데이트가 완료되면 위도, 경도에 해당하는 위치의 정보를 추출하도록 합니다.
2. 맵 뷰 중앙 위치의 정보
위의 gif에서는 화면이 이동할 때마다 중앙의 위치를 가져오는 것을 확인할 수 있습니다.
내 위치와 마찬가지로 동일한 방법으로 찾으면 되는데 이때 주의할 점은 reverseGeocodeLocation를 짧은 시간 안에 너무 자주 호출을 하면 안 된다는 점입니다.
짧은 시간에 많은 호출을 할 경우 결과를 받아올 수 없게 됩니다.
mapViewDidChangeVisibleRegion을 이용하여 뷰의 가시영역이 변경될 때마다 맵 뷰의 중앙 위치를 표시할 것인데 마지막 변경에만 작업할 수 있게 하겠습니다.
var runTimeInterval: TimeInterval? // 마지막 작업을 설정할 시간 let mTimer: Selector = #selector(Tick_TimeConsole) // 위치 확인 타이머 override func viewDidLoad() { super.viewDidLoad() Timer.scheduledTimer(timeInterval: 0.25, target: self, selector: mTimer, userInfo: nil, repeats: true) }
viewDidLoad에 타이머를 추가해 주도록 합니다. 앞으로 맵 뷰의 중앙 위치 정보는 타이머에서 변경하도록 할 것입니다.
extension ViewController: MKMapViewDelegate { func mapViewDidChangeVisibleRegion(_ mapView: MKMapView) { runTimeInterval = Date().timeIntervalSinceReferenceDate } }
뷰의 가시영역이 변경이 언제가 마지막인지 확인할 수 있도록 델리게이트에서 시간을 체크하도록 합니다.
@objc func Tick_TimeConsole() { guard let timeInterval = runTimeInterval else { return } let interval = Date().timeIntervalSinceReferenceDate - timeInterval if interval < 0.25 { return } let coordinate = mapkit.centerCoordinate let location = CLLocation(latitude: coordinate.latitude, longitude: coordinate.longitude) // 지정된 위치의 지오 코드 요청 CLGeocoder().reverseGeocodeLocation(location) { (placemarks, error) in if let pm: CLPlacemark = placemarks?.first { let address: String = "\(pm.country ?? "") \(pm.administrativeArea ?? "") \(pm.locality ?? "") \(pm.subLocality ?? "") \(pm.name ?? "")" self.centerMainTitle.text = "화면 중앙 위치" self.centerSubTitle.text = address } else { self.centerMainTitle.text = "" self.centerSubTitle.text = "" } } runTimeInterval = nil }
확인된 마지막 변경 시간에서 0.25초가 이상 경과해야 위치 정보를 업데이트할 수 있도록 했습니다.
var annotations:[MKAnnotation] = [] let categoryArray = ["카페", "편의점", "은행", "주유소", "선별 진료소"] extension ViewController: UICollectionViewDelegate, UICollectionViewDelegateFlowLayout, UICollectionViewDataSource { func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return categoryArray.count } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CategoryCell", for: indexPath) as! CategoryCell cell.categoryLabel.text = categoryArray[indexPath.row] return cell } func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { setSearchAnnotation(query: self.categoryArray[indexPath.row]) } func setSearchAnnotation(query:String) { annotations.removeAll() mapkit.removeAnnotations(mapkit.annotations) let request = MKLocalSearch.Request() request.naturalLanguageQuery = "\(query)" request.region = mapkit.region let search = MKLocalSearch(request: request) search.start { (response, error) in guard let responseMap = response?.mapItems else { return } for item in responseMap { let annotation = MKPointAnnotation() annotation.coordinate = item.placemark.coordinate annotation.title = item.name annotation.subtitle = item.phoneNumber self.annotations.append(annotation) } self.mapkit.addAnnotations(self.annotations) } } }
'ios' 카테고리의 다른 글
[ios - Swift] Circle Progressbar 만들기 (CALayer) (0) 2021.01.08 [ios - Swift] FileManager 사용한 저장, 불러오기 (0) 2021.01.05 [ios - Swift] MapView 사용하기 (MKMapView 1 / 2) (1) 2020.12.22 [ios - Swift] Alamofire Example (0) 2020.12.21 [ios - Swift] PHCachingImageManager 사용하기 (0) 2020.12.14