23.01.13 - ์ฑ์ ์ฒ์ ์ค์นํ์ ๋ ํ์ฌ ์์น๋ก ์ด๋ํ์ง ์๋ ์ค๋ฅ ํด๊ฒฐ
์ง๋ ๋ฒ ํ๋กํ ํ์ ์ ์ด์ด ์ด๋ฒ ์ฃผ๋ถํฐ๋ MVP๋ฅผ ์งํํ๊ณ ์๋ค.
๊ธฐ์กด์ ๋๋ฏธ ๋ฐ์ดํฐ๋ก ๊ตฌํํ๋ ๊ฒ๋ค์ ์ค์ FireStore์ ์ฐ๋ํ๊ณ ๊ตฌํํ์ง ๋ชปํ๋ ๋ถ๋ถ๋ค์ ๊ตฌํํ๋ ๊ฒ์ ๋ชฉํ๋ก ์ก์๋ค.
์ด๋ฒ ์ฃผ์ ๊ตฌํํ๋ ค๋ ๊ธฐ๋ฅ์ ์๋์ ๊ฐ๋ค.
1. ์ฌ์ฉ์๊ฐ ์ง๋๋ฅผ ์์ง์ด๋ฉด ์์ง์ธ ์ขํ์ ๋ํ ๋๋ก๋ช ์ฃผ์๋ฅผ ์ค์๊ฐ์ ๊ฐ์ ธ์ด
2. ์ฌ์ฉ์๊ฐ ์ง๋๋ฅผ ์์ง์ด๋ฉด ๋ง์ปค๊ฐ ์ด์ง ์๋ก ์ฌ๋ผ๊ฐ๊ณ , ์์ง์์ด ๋ฉ์ถ๋ฉด ๋ง์ปค๊ฐ ๋ค์ ๋ด๋ ค์ด
3. ์ฌ์ฉ์์ ํ์ฌ ์์น๋ฅผ ๊ฐ์ ธ์ค๊ณ , ๋ฒํผ์ ํด๋ฆญํ๋ฉด ํ์ฌ ์์น๋ก ์ง๋์ Focus๋ฅผ ๋ณ๊ฒฝํจ
ํ๋์ฉ ์ดํด๋ณด๋๋ก ํ์.
1. ์ฌ์ฉ์๊ฐ ์ง๋๋ฅผ ์์ง์ด๋ฉด ์์ง์ธ ์ขํ์ ๋ํ ๋๋ก๋ช ์ฃผ์๋ฅผ ์ค์๊ฐ์ผ๋ก ๊ฐ์ ธ์ค๊ธฐ
๋ง์ด ์ข ๊ธธ๋ค.
๊ฐ๋จํ๊ฒ ์ค๋ช ํ์๋ฉด ์ง๋๋ฅผ ์์ง์์ ๋ ๋๋ก๋ช ์ฃผ์ ๊ฐ์ ธ์จ๋ค๊ณ ์๊ฐํ๋ฉด ๋๋ค.
์ด ๊ธฐ๋ฅ์ ์ง๋ ๋ฒ ํ๋กํ ํ์ ๋๋ ๊ตฌํํ์ง ๋ชปํ ๊ธฐ๋ฅ์ด์์ง๋ง, ๊ณต์๋ฌธ์๋ฅผ ํ๋ ํ๋ ์ดํด๋ณด๋ฉด์ ๊ฒฐ๊ตญ์๋ ํด๊ฒฐํ๋ค.
์ฐ์ ๊ธฐ์กด ๊ตฌํ ๋ฐฉ์์ ์ดํด๋ณด๋ฉด,
CLLocationManagerDelgate๋ฅผ ์ฑํํ๊ณ mapViewDidChangeVisibleRegion(_ mapView: MKMapView) ๋ฉ์๋๋ก ์ง๋๊ฐ ์์ง์ผ ๋ ์์น ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ค๋ ค๊ณ ํ์๋ค. ํด๋น ๋ฉ์๋๋ ์ง๋์์ ๋ณด์ด๋ ์์ญ์ด ๋ณ๊ฒฝ๋๋ฉด ํธ์ถ๋๋ ๋ฉ์๋์ด๋ค. ๋ฐ๋ผ์ ์ฌ์ฉ์๊ฐ ์ง๋๋ฅผ ์์ง์ด๋ฉด ์ด ๋ฉ์๋๊ฐ ํธ์ถ๋๊ณ , ์ด ๋ฉ์๋ ๋ด๋ถ์์ ์, ๊ฒฝ๋๋ฅผ ๋๋ก๋ช ์ฃผ์๋ก ๋ณํํด์ฃผ๋ ReverseGeocoding์ ์งํํ๋ฉด ๋ ๊ฒ ๊ฐ์๋ค.
์ฌ์ฉ์๊ฐ ์ง๋๋ฅผ ์์ง์ผ ๋, ์ฆ๊ฐ์ ์ผ๋ก ์์น ์ ๋ณด๋ ์ ๊ฐ์ ธ์๋ค.
ํ์ง๋ง ์ด๋ฅผ ๋๋ก๋ช ์ฃผ์๋ก ๋ณํํ๊ธฐ ์ํด์ reverseGeocoding์ ์ ์ฉํ๋ฉด ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ค.
์๋ฌ๋ฅผ ์ฝ์ด๋ณด๋ฉด API ํธ์ถ์ ๋๋ฌด ์์ฃผํด์ฃผ๊ณ ์๋ค๋ ๊ฒ
์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด์ ๊ฐ์ฅ ๋จผ์ ๋ ์ค๋ฅธ ๋ฐฉ๋ฒ์
์, ๊ฒฝ๋๊ฐ ๋ฐ๋ ๋๋ง๋ค ํธ์ถํ๋ ๊ฒ์ด ์๋๋ผ, TimeInterval์ ์ค์ ํน์ ์๊ฐ์ ํ ๋ฒ์ฉ๋ง ํธ์ถ๋๋๋ก ํ๋ ๋ฐฉ๋ฒ์ด์๋ค.
๊ฒ์ํด๋ณด๋ ์ด๋ค ๋ถ์ด ์ด ๋ฐฉ์์ผ๋ก ๊ฐ์ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ณ ์์๋ค.
ํ์ง๋ง ๋ญ๊ฐ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ผ๋ก ์ ๊ทผํ๊ณ ์ถ์๋ค.
์ ์ ํ๋ฌํฐ๋ก GoogleMaps์ ์ฌ์ฉํ ๋ ๋น์ทํ ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ ๋ฉ์๋๊ฐ ์์๊ณ ,
MapKit์๋ ์์ ๊ฒ์ด๋ผ๊ณ ์๊ฐํ๊ณ ๊ณต์๋ฌธ์๋ฅผ ์ฐพ์๋ดค๋ค.
์ญ์๋ Mapkit์์๋ ์ ๊ณตํ๊ณ ์์๋ค.
๊ฐ๊ฐ์ ๋ํด์ ๊ฐ๋จํ๊ฒ ์ค๋ช ํ์๋ฉด
mapView(_:regionWillChangeAnimated:) ๋ Position์ด ๋ณ๊ฒฝ๋๊ธฐ ์ง์ ์
mapViewDidChangeVisibleRegion ๋ Position์ด ๋ณ๊ฒฝ๋ ๋
mapView(MKMapView, regionDidChangeAnimated:) ๋ Position ๋ณ๊ฒฝ์ด ์ข ๋ฃ๋ ํ์ ํธ์ถ๋๋ค.
๊ทธ ์ค์์ ๋๋ ์ธ ๋ฒ์งธ ๋ฉ์๋๋ฅผ ํตํด ReverseGeocoding์ ์งํํ๊ณ ,
์ดํด๋ฅผ ๋๊ธฐ ์ํด ํด๋น ๋ฉ์๋ ๋ด๋ถ์ print๋ฌธ์ ์ฐ์ด๋ดค๋ค.
์ด๋ ๊ฒ ์ฌ์ฉ์๊ฐ ์ง๋๋ฅผ ์์ง์ด๊ณ ,
์๋, ๊ฒฝ๋๊ฐ ์กฐ๊ธ์ด๋ผ๋ ๋ฐ๋๋ฉด mapViewDidChangeVisibleRegion ๋ฉ์๋๊ฐ ํธ์ถ๋๋ฉด์
func convertCLLocationToAddress(location: CLLocation) {
let geocoder = CLGeocoder()
// Location To Address
geocoder.reverseGeocodeLocation(location) { placemarks, error in
if error != nil {
return
}
guard let placemark = placemarks?.first else { return }
self.startPlace = "\(placemark.country ?? "") \(placemark.locality ?? "") \(placemark.name ?? "")"
}
}
์์ ๊ตฌํํ convertCLLocationToAddress ๋ฉ์๋๊ฐ ํธ์ถ๋๋๋ก ๊ตฌํํ๋ค.
convertCLLocationToAddress์ Swift์์ ์์ฒด์ ์ผ๋ก ์ ๊ณตํ๋ reverseGeocodeLocation์ ํ์ฉํ๋ค.
์ด๋ ๊ฒ ์, ๊ฒฝ๋๋ฅผ ๋๋ก๋ช ์ฃผ์๋ก ๋ณํํ๋ ๊ธฐ๋ฅ์ ๊ตฌํํ๋ค.
2. ์ฌ์ฉ์๊ฐ ์ง๋๋ฅผ ์์ง์ด๋ฉด ๋ง์ปค๊ฐ ์ด์ง ์๋ก ์ฌ๋ผ๊ฐ๊ณ , ์์ง์์ด ๋ฉ์ถ๋ฉด ๋ง์ปค๊ฐ ๋ค์ ๋ด๋ ค์ด
๋ค์์ ๋ ๋ฒ์งธ, ์ญ์ ๋ง์ด ๊ธธ๋ค.
์ฌ์ฉ์๊ฐ ์ง๋๋ฅผ ์์ง์ด๋ฉด ๋ง์ปค์ ํน์ ํจ๊ณผ๋ฅผ ์ฃผ๊ณ ์ถ์๋ค.
์ด ๊ธฐ๋ฅ์ด ์ ํ์ํ๋๊ณ ๋ฌผ์ด๋ณธ๋ค๋ฉด...
์ฌ์ฉ์ ์ธํฐ๋์ ์ ์ข์ํ๊ธฐ์...
๋ฐฐ๋ฏผ์ด๋ ์์นด์์๋ ์ด ๊ธฐ๋ฅ์ ์ฐพ์๋ณผ ์ ์๋ค.
์๋ฌดํผ ์ด ๊ธฐ๋ฅ์ด ์ข์์ ๊ตฌํ์ ํ๋ ค๊ณ ํ๊ณ , ์ญ์ ์์์ ์ธ๊ธํ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ค.
์ฌ์ฉ์๊ฐ ์ง๋๋ฅผ ์์ง์ด๊ณ ์๋ค๋ ์ํ๋ฅผ ์ ์ฅํ๊ธฐ ์ํ ํ๋กํผํฐ๋ฅผ ์ ์ํด์ ๊ตฌํํ๋ค.
@Published var isChanging: Bool = false // ์ง๋์ ์์ง์ ์ฌ๋ถ๋ฅผ ์ ์ฅํ๋ ํ๋กํผํฐ
// ... ์๋ต
// MARK: - MapView์์ ํ๋ฉด์ด ์ด๋ํ๋ฉด ํธ์ถ๋๋ ๋ฉ์๋
func mapViewDidChangeVisibleRegion(_ mapView: MKMapView) {
DispatchQueue.main.async {
self.isChanging = true
}
}
// MARK: - MapView์์ ํ๋ฉด ์ด๋์ด ์ข
๋ฃ๋๋ฉด ํธ์ถ๋๋ ๋ฉ์๋
func mapView(_ mapView: MKMapView, regionDidChangeAnimated: Bool) {
let location: CLLocation = CLLocation(latitude: mapView.centerCoordinate.latitude, longitude: mapView.centerCoordinate.longitude)
self.convertLocationToAddress(location: location)
DispatchQueue.main.async {
self.isChanging = false
}
}
// ... ์๋ต
// MARK: - location์ ๋๋ก๋ช
์ฃผ์๋ก ๋ณํํด์ฃผ๋ ๋ฉ์๋
func convertLocationToAddress(location: CLLocation) {
let geocoder = CLGeocoder()
geocoder.reverseGeocodeLocation(location) { placemarks, error in
if error != nil {
return
}
guard let placemark = placemarks?.first else { return }
self.startPlace = "\(placemark.country ?? "") \(placemark.locality ?? "") \(placemark.name ?? "")"
}
}
3. ์ฌ์ฉ์์ ํ์ฌ ์์น๋ฅผ ๊ฐ์ ธ์ค๊ณ , ๋ฒํผ์ ํด๋ฆญํ๋ฉด ํ์ฌ ์์น๋ก ์ง๋์ Focus๋ฅผ ๋ณ๊ฒฝํจ
๋ง์ง๋ง ์ธ ๋ฒ์งธ๋ ์ฌ์ฉ์์ ํ์ฌ ์์น๋ฅผ ๊ฐ์ ธ์ค๊ณ , ๋ฒํผ์ ํด๋ฆญํ๋ฉด ์ฌ์ฉ์์ ํ์ฌ ์์น๋ก ์ด๋ํ๋ ๊ธฐ๋ฅ์ด๋ค.
์ฐ์ ์ ์ฌ์ฉ์์ ์์น๋ฅผ ๊ฐ์ ธ์์ผ ํ๊ธฐ์, ์์น ๊ถํ์ ์์ฒญํ๋ ์์ ์ ๋จผ์ ์งํํ๋ค.
info ํ์ผ์ ์๋์ฒ๋ผ Key๋ฅผ ์ถ๊ฐํ๊ณ
์ฌ์ฉ์๊ฐ ์์น ๊ถํ์ ์ค์ ํ๋์ง ํ์ธํ๊ณ , ์์น ๊ถํ์ ์์ฒญํ๋ ๋ฉ์๋๋ฅผ ๊ตฌํํ๋ค.
// MARK: - ์ฌ์ฉ์์ ์์น ๊ถํ ์ฌ๋ถ๋ฅผ ํ์ธํ๊ณ ์์ฒญํ๊ฑฐ๋ ํ์ฌ ์์น MapView๋ฅผ ์ด๋ํ๋ ๋ฉ์๋
func configureLocationManager() {
mapView.delegate = self
manager.delegate = self
let status = manager.authorizationStatus
if status == .notDetermined {
manager.requestAlwaysAuthorization()
} else if status == .authorizedAlways || status == .authorizedWhenInUse {
self.moveFocusOnUserLocation()
}
}
// MARK: - ์ฌ์ฉ์์ ํ์ฌ ์์น๋ก MapView๋ฅผ ์ด๋ํ๋ ๋ฉ์๋
func moveFocusOnUserLocation() {
mapView.showsUserLocation = true
mapView.setUserTrackingMode(.follow, animated: true)
}
๋ํ ์ฌ์ฉ์๊ฐ ์์น ๊ถํ์ ๋ณ๊ฒฝํ๋ฉด ํธ์ถ๋๋ ๋ฉ์๋์์๋ moveFocusOnUserLocation์ ํธ์ถํ๋ค.
๊ณต์๋ฌธ์๋ฅผ ๋ณด๋ค๊ฐ ๊ธฐ์กด์ ์ฌ์ฉํ ๋ฉ์๋๋ Deprecated ๋ ๋ฉ์๋์ฌ์ ์๋ก์ด ๋ฉ์๋๋ก ๋ณ๊ฒฝํ๋ค.
// MARK: - ์ฌ์ฉ์์๊ฒ ์์น ๊ถํ์ด ๋ณ๊ฒฝ๋๋ฉด ํธ์ถ๋๋ ๋ฉ์๋
// Deprecated
// func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
//
// if status == .authorizedAlways || status == .authorizedWhenInUse {
// self.moveFocusOnUserLocation()
// }
// }
func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
if manager.authorizationStatus == .authorizedAlways || manager.authorizationStatus == .authorizedWhenInUse {
self.moveFocusOnUserLocation()
}
}
์ฌ์ค locationManagerDidChangeAuthorization ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ง ์์๋ ์ฑ์ ๊ตฌํํ๋ ค๋ ๊ธฐ๋ฅ์ ์ ์์ ์ผ๋ก ์๋ํ๋ค.
๊ทธ ์ด์ ๋ ํด๋น ๋ฉ์๋๋ ์ฌ์ฉ์๊ฐ ์์น ๊ถํ์ ๋ณ๊ฒฝํ์ ๋ ํธ์ถ๋๋ ๋ฉ์๋์ด๊ธฐ ๋๋ฌธ์ด๋ค.
๊ตฌํํ ์ฝ๋ ์์์๋ LocationManager๊ฐ EnvironmentObject๋ก ์์ฑ๋์ด ์๊ณ ,
๋ฐ๋ผ์ ์ฑ์ด ์คํ๋ ๋ LocationManager์ ์ธ์คํด์ค๋ฅผ ์์ฑํ๋ค.
๊ทธ ์ดํ์ configureLocationManger ๋ฉ์๋๊ฐ ํธ์ถ๋๋ ๋ฐฉ์์ด๋ค.
๋ฐ๋ผ์ ์ฌ์ฉ์๊ฐ ์์น ๊ถํ์ ๋ณ๊ฒฝํ๋์ง์ ๊ด๊ณ ์์ด ์์น ๊ถํ์ด ํ์ฉ ์ํ์ด๋ฉด,
์ฌ์ฉ์์ ํ์ฌ ์์น๋ก ์ด๋ํ๊ฒ ๋๋ค.
๊ทธ๋ฆฌ๊ณ ๊ณต์๋ฌธ์๋ฅผ ์ฝ์ด๋ณด๋ฉด ์ ์ ์๋๋ฐ,
ํด๋น ๋ฉ์๋๋ LocationManager์ ์ธ์คํด์ค๊ฐ ์์ฑ๋๊ฑฐ๋ ์์น ๊ถํ์ด ๋ณ๊ฒฝ๋ ๋ ํธ์ถ๋๋ค๊ณ ๋์์๋ค.
์ค์ ๋ก ์ฑ์ด ์คํ๋ ๋ EnvironmentObject๋ก LocationManager์ ์ธ์คํด์ค๋ฅผ ์์ฑํ๋ฏ๋ก ์ฑ์ ์์ฑ๋๋ฅผ ์ข ๋ ๋ํ๋ค๋ฉด?
configureLocationManager์์ moveFocusOnUserLocation๋ฅผ ํธ์ถํ์ง ์๊ณ ,
locationManagerDidChangeAuthorization์์ ํธ์ถํ๋ ๊ฒ์ด ๋ ์ ์ ํ๋ค๊ณ ์๊ฐํ๋ค.
์๋ฌดํผ ์ฌ๊ธฐ๊น์ง ํด์ ๋ฒ๊ทธ ํด๊ฒฐ~ ๐
(23.01.13 - ์ฑ์ ์ฒ์ ์ค์นํ์ ๋ ํ์ฌ ์์น๋ก ์ด๋ํ์ง ์๋ ์ค๋ฅ ํด๊ฒฐ)
์ฐ์ , ํ๋ก์ ํธ์ ๋ํด ๊ฐ๋จํ๊ฒ ์ค๋ช ํ์๋ฉด ๊ฐ๋จํ ์ผ๊ธฐ ์ฑ์ด๊ณ , ์ผ๊ธฐ๋ฅผ ์์ฑํ ๋ ์ฌ์ฉ์์ ์์น๋ฅผ ๋ฑ๋กํ ์ ์๋๋ก ๊ตฌํํ ๊ณํ์ด์๋ค.
๋ํ ์ผ๊ธฐ ์์ฑ ํ์ด์ง์์ MapView๋ฅผ .onSheet(๋๋ .FullScreen)๋ก ์ ์ฉํ๊ณ ์์๋ค.
์ด ํ๋ก์ ํธ์ ๊ธฐ์กด ์ฝ๋๋ฅผ ๊ทธ๋๋ก ์ ์ฉ์ ํ๋๋ฐ,
์ฑ์ ์ฒ์ ์คํํ์ ๋ ์์น ๊ถํ์ ๋ถ์ฌํ๊ณ , ์ดํ์ MapView๊ฐ ์ ์์ ์ผ๋ก ์๋ํ์ง ์๋ ์ค๋ฅ๊ฐ ์์๋ค.
์ค๋ฅ๋ฅผ ์ดํด๋ณด๋ฉด,
1. ์ฌ์ฉ์์ ํ์ฌ ์์น๋ฅผ ๊ฐ์ ธ์ค์ง ๋ชปํจ.
2. ๋ค๋ฅธ ๊ธฐ๋ฅ(ํ๋ฉด์ ์์ง์ผ ๋ ๋ง์ปค๊ฐ ์, ์๋๋ก ์์ง์ด๋ ๊ธฐ๋ฅ, ์ค์๊ฐ์ผ๋ก ๋๋ก๋ช ์ฃผ์๋ฅผ ๊ฐ์ ธ์ค๋ ๊ธฐ๋ฅ)์ด ์ ์์ ์ผ๋ก ์๋ํ์ง ์์.
์ฝ๋๋ฅผ ๋ค์ ํ๋ ํ๋ ์ดํด๋ณด๋ฉด์ ๋ด๋ฆฐ ๊ฒฐ๋ก ์ LocationManager ์ธ์คํด์ค์ ์์ฑ ์๊ธฐ์๋ค.
๊ธฐ์กด ์ฝ๋๋ MapView์์ LocationManager์ ์ธ์คํด์ค๋ฅผ ์์ฑํ๊ณ ์์๋ค.
์ด๋ฅผ MapView๊ฐ ๋ณด์ฌ์ง๋ ํ์ด์ง๊ฐ ์๋ ์ด์ ํ์ด์ง(์ผ๊ธฐ๋ฅผ ์์ฑํ๋ ํ์ด์ง)์์ ์์ฑํ๊ณ ํ๋ผ๋ฏธํฐ๋ก ๋๊ฒจ์ฃผ๋ ๋ฐฉ์์ผ๋ก ๋ณ๊ฒฝํ๊ณ ,
์ค๋ฅ๋ฅผ ํด๊ฒฐํ ์ ์์๋ค.
์ค๋ฅ๋ฅผ ํด๊ฒฐํ๋ฉด์ ๋ถํ์ํ ์ฝ๋๋ฅผ ์ ๊ฑฐํ๊ณ , ์์์ ์ธ๊ธํ moveFocusOnUserLocation์ ์ญํ ์
locationManagerDidChangeAuthorization์์ ์ฒ๋ฆฌํ๋๋ก ๋ณ๊ฒฝํ๋ค.
๋ํ didUpdateLocation ๋ฉ์๋์ ๊ฒฝ์ฐ ํน์ ์กฐ๊ฑด์์๋ง ์คํ๋๊ณ , ์ด ๋ฉ์๋๋ฅผ ํธ์ถํ์ง ์์๋ ๊ธฐ๋ฅ์ ์ ์์ ์ผ๋ก ๊ตฌํํ ์ ์๊ธฐ์ ๋ด๋ถ์ ์ฝ๋๋ฅผ ์ง์์คฌ๋ค.
์ ์ฒด ์ฝ๋
// ... ์๋ต
// MARK: - MapView ์ปค์คํ
struct MapViewCoordinator: UIViewRepresentable {
@ObservedObject var locationManager: LocationManager
func makeUIView(context: Context) -> some UIView {
return locationManager.mapView
}
func updateUIView(_ uiView: UIViewType, context: Context) { }
}
//
// LocationManager.swift
//
// Created by ๊ณ ๋ on 2022/12/20.
//
import Foundation
import MapKit
class LocationManager: NSObject, ObservableObject, MKMapViewDelegate, CLLocationManagerDelegate {
@Published var mapView: MKMapView = .init()
@Published var isChanging: Bool = false // ์ง๋์ ์์ง์ ์ฌ๋ถ๋ฅผ ์ ์ฅํ๋ ํ๋กํผํฐ
@Published var currentPlace: String = "" // ํ์ฌ ์์น์ ๋๋ก๋ช
์ฃผ์๋ฅผ ์ ์ฅํ๋ ํ๋กํผํฐ
private var manager: CLLocationManager = .init()
private var currentGeoPoint: CLLocationCoordinate2D? // ํ์ฌ ์์น๋ฅผ ์ ์ฅํ๋ ํ๋กํผํฐ
override init() {
super.init()
self.configureLocationManager()
}
// MARK: - ์ฌ์ฉ์์ ์์น ๊ถํ ์ฌ๋ถ๋ฅผ ํ์ธํ๊ณ ์์ฒญํ๊ฑฐ๋ ํ์ฌ ์์น MapView๋ฅผ ์ด๋ํ๋ ๋ฉ์๋
func configureLocationManager() {
mapView.delegate = self
manager.delegate = self
let status = manager.authorizationStatus
if status == .notDetermined {
manager.requestAlwaysAuthorization()
} else if status == .authorizedAlways || status == .authorizedWhenInUse {
mapView.showsUserLocation = true // ์ฌ์ฉ์์ ํ์ฌ ์์น๋ฅผ ํ์ธํ ์ ์๋๋ก
}
}
// MARK: - MapView์์ ํ๋ฉด์ด ์ด๋ํ๋ฉด ํธ์ถ๋๋ ๋ฉ์๋
func mapViewDidChangeVisibleRegion(_ mapView: MKMapView) {
DispatchQueue.main.async {
self.isChanging = true
}
}
// MARK: - MapView์์ ํ๋ฉด ์ด๋์ด ์ข
๋ฃ๋๋ฉด ํธ์ถ๋๋ ๋ฉ์๋
func mapView(_ mapView: MKMapView, regionDidChangeAnimated: Bool) {
let location: CLLocation = CLLocation(latitude: mapView.centerCoordinate.latitude, longitude: mapView.centerCoordinate.longitude)
self.convertLocationToAddress(location: location)
DispatchQueue.main.async {
self.isChanging = false
}
}
// MARK: - ํน์ ์์น๋ก MapView์ Focus๋ฅผ ์ด๋ํ๋ ๋ฉ์๋
func mapViewFocusChange() {
print("[SUCCESS] Map Focus Changed")
let span = MKCoordinateSpan(latitudeDelta: 0.005, longitudeDelta: 0.005)
let region = MKCoordinateRegion(center: self.currentGeoPoint ?? CLLocationCoordinate2D(latitude: 37.394776, longitude: 127.11116), span: span)
mapView.setRegion(region, animated: true)
}
// MARK: - ์ฌ์ฉ์์๊ฒ ์์น ๊ถํ์ด ๋ณ๊ฒฝ๋๋ฉด ํธ์ถ๋๋ ๋ฉ์๋ (LocationManager ์ธ์คํด์ค๊ฐ ์์ฑ๋ ๋๋ ํธ์ถ)
func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
if manager.authorizationStatus == .authorizedAlways || manager.authorizationStatus == .authorizedWhenInUse {
guard let location = manager.location else {
print("[ERROR] No Location")
return
}
self.currentGeoPoint = location.coordinate // ํ์ฌ ์์น๋ฅผ ์ ์ฅํ๊ณ
self.mapViewFocusChange() // ํ์ฌ ์์น๋ก MapView๋ฅผ ์ด๋
self.convertLocationToAddress(location: location)
}
}
// MARK: - ์ฌ์ฉ์์ ์์น๊ฐ ๋ณ๊ฒฝ๋๋ฉด ํธ์ถ๋๋ ๋ฉ์๋
/// startUpdatingLocation ๋ฉ์๋ ๋๋ requestLocation ๋ฉ์๋๋ฅผ ํธ์ถํ์ ๋์๋ง ์ด ๋ฉ์๋๊ฐ ํธ์ถ
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
print("[SUCCESS] Did Update Locations")
}
// MARK: - ์ฌ์ฉ์์ ํ์ฌ ์์น๋ฅผ ๊ฐ์ ธ์ค๋ ๊ฒ์ ์คํจํ์ ๋ ํธ์ถ๋๋ ๋ฉ์๋
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print(error)
}
// MARK: - location์ ๋๋ก๋ช
์ฃผ์๋ก ๋ณํํด์ฃผ๋ ๋ฉ์๋
func convertLocationToAddress(location: CLLocation) {
let geocoder = CLGeocoder()
geocoder.reverseGeocodeLocation(location) { placemarks, error in
if error != nil {
return
}
guard let placemark = placemarks?.first else { return }
self.startPlace = "\(placemark.country ?? "") \(placemark.locality ?? "") \(placemark.name ?? "")"
}
}
}
๋ค์ ๊ฒ์๋ฌผ์ ๋ค์ด๋ฒ ๊ฒ์ API์ Katech ์ขํ๋ฅผ WGS ์ขํ๋ก ๋ณํํ๋ ๋ค์ด๋ฒ Maps API์ ํ์ฉํด์
๋ชฉ์ ์ง๋ฅผ ์ง๋ ์์ ํ์ํด์ฃผ๋ ๊ธฐ๋ฅ์ ๋ํ ๊ฒ์๋ฌผ๋ก!