아이폰의 현재 위도 및 경도 정보 추출 및 상세주소 정보 추출
info.plist 퍼미션 입력
Privacy - Location When In Use Usage Description - 앱이 사용중일때만 가져오기
Privacy - Location Always and When In Use Usage Description - 앱을 사용안해도 항상 가져오기
import UIKit
import CoreLocation
class LocationService: NSObject {
static let shared = LocationService()
let locationManager = CLLocationManager()
var locationClosur: ((_ latitude: Double, _ longitude: Double) -> Void)!
deinit {
log(direction: .ETC, ofType: self, datas: "deinit")
}
override init() {
super.init()
locationManager.delegate = self
}
///didUpdateLocations Delegate 실행
func startLocationUpdate() {
locationManager.startUpdatingLocation()
}
///didUpdateLocations Delegate 정지
func stopLocationUpdate() {
locationManager.stopUpdatingLocation()
}
/// location 정보로 주소 추출
func getLocationAddress(completed: @escaping (String?) -> Void){
if let latitude = locationManager.location?.coordinate.latitude,
let longitude = locationManager.location?.coordinate.longitude {
//참고자료 : https://velog.io/@rose6649/iOS-CLGeocoder-%EC%9C%84%EB%8F%84%EA%B2%BD%EB%8F%84-%EC%A0%95%EB%B3%B4%EB%A1%9C-%EC%A7%80%EC%97%AD%EB%AA%85-%EA%B0%80%EC%A0%B8%EC%98%A4%EA%B8%B0
let findLocation: CLLocation = CLLocation(latitude: latitude, longitude: longitude)
let geocoder = CLGeocoder.init()
let local: Locale = Locale(identifier: "Ko-kr") // Korea
geocoder.reverseGeocodeLocation(findLocation, preferredLocale: local) { (placemarks, error) in
if error != nil {
return
}
var address: String = ""
if let placemark = placemarks?.last {
log(direction: .OBSERVER, ofType: self, datas:
"국적 : \(String(describing: placemark.country))",
"시/도 : \(String(describing: placemark.administrativeArea))",
"시 : \(String(describing: placemark.locality))",
"구 : \(String(describing: placemark.subLocality))",
"동 / 가 : \(String(describing: placemark.thoroughfare))",
"번지 : \(String(describing: placemark.subThoroughfare))")
// 국적 (ex : 대한민국)
if let country = placemark.country {
address += country + " "
}
// 시/도 (ex : 광주광역시 / 경기도)
if let administrativeArea = placemark.administrativeArea {
address += administrativeArea + " "
// 시 (ex : 평택시) - administrativeArea (경기도) 일 경우 locality 시가 들어옴.
// 이 외 administrativeArea 시 일 경우 동일한 데이터 표시됨.
// administrativeArea와 locality 같을 경우 패스시킴
if let locality = placemark.locality {
if administrativeArea.compare(locality, options: .caseInsensitive) != .orderedSame {
address += locality + " "
}
}
}
// 구 (ex : 북구)
if let subLocality = placemark.subLocality {
address += subLocality + " "
}
// 동 / 가 (ex : 매곡동 / 북문로3가)
if let thoroughfare = placemark.thoroughfare {
address += thoroughfare + " "
}
// 번지 (ex : 89번지)
if let subThoroughfare = placemark.subThoroughfare {
address += subThoroughfare
}
completed(address)
}
}
}
completed(nil)
}
private func checkUserDeviceLocationServiceAuthorization() {
let authorizationStatus: CLAuthorizationStatus
// 앱의 권한 상태 가져오는 코드
if #available(iOS 14.0, *) {
authorizationStatus = locationManager.authorizationStatus
}else {
authorizationStatus = CLLocationManager.authorizationStatus()
}
// 권한 상태값에 따라 분기처리를 수행하는 메서드 실행
checkUserCurrentLocationAuthorization(authorizationStatus)
}
private func checkUserCurrentLocationAuthorization(_ status: CLAuthorizationStatus) {
switch status {
case .notDetermined:
// 사용자가 권한에 대한 설정을 선택하지 않은 상태
// 권한 요청을 보내기 전에 desiredAccuracy 설정 필요
locationManager.desiredAccuracy = kCLLocationAccuracyBest
// 권한 요청을 보낸다.
locationManager.requestWhenInUseAuthorization()
case .denied, .restricted:
// 사용자가 명시적으로 권한을 거부했거나, 위치 서비스 활성화가 제한된 상태
// 시스템 설정에서 설정값을 변경하도록 유도한다.
// 시스템 설정으로 유도하는 커스텀 얼럿
showRequestLocationServiceAlert()
case .authorizedWhenInUse:
// 앱을 사용중일 때, 위치 서비스를 이용할 수 있는 상태
// manager 인스턴스를 사용하여 사용자의 위치를 가져온다.
locationManager.startUpdatingLocation()
default:
print("Default")
}
}
private func showRequestLocationServiceAlert() {
let requestLocationServiceAlert = UIAlertController(title: "위치 정보 이용", message: "위치 서비스를 사용할 수 없습니다.\n디바이스의 '설정 > 개인정보 보호'에서 위치 서비스를 켜주세요.", preferredStyle: .alert)
let goSetting = UIAlertAction(title: "설정으로 이동", style: .destructive) { _ in
if let appSetting = URL(string: UIApplication.openSettingsURLString) {
UIApplication.shared.open(appSetting)
}
}
let cancel = UIAlertAction(title: "취소", style: .default) { _ in
// async { await self?.reloadData() }
}
requestLocationServiceAlert.addAction(cancel)
requestLocationServiceAlert.addAction(goSetting)
guard let topVC = UIApplication.currentTopViewController() else {
return
}
topVC.present(requestLocationServiceAlert, animated: true)
}
}
//MARK: CLLocationManagerDelegate
extension LocationService: CLLocationManagerDelegate {
// 사용자의 위치를 성공적으로 가져왔을 때 호출
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
// 위치 정보를 배열로 입력받는데, 마지막 index값이 가장 정확하다고 한다.
if let coordinate = locations.last?.coordinate {
// ⭐️ 사용자 위치 정보 사용(위도, 경도 가져오기)
log(direction: .ETC, ofType: self, datas: "위도 : \(coordinate.latitude)","경도 : \(coordinate.longitude)")
self.locationClosur?(coordinate.latitude, coordinate.longitude)
}
}
// 사용자가 GPS 사용이 불가한 지역에 있는 등 위치 정보를 가져오지 못했을 때 호출
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
log(direction: .ERROR, ofType: self, datas: error.localizedDescription)
}
// 앱에 대한 권한 설정이 변경되면 호출 (iOS 14 이상)
func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
// 사용자 디바이스의 위치 서비스가 활성화 상태인지 확인하는 메서드 호출
checkUserDeviceLocationServiceAuthorization()
}
// 앱에 대한 권한 설정이 변경되면 호출 (iOS 14 미만)
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
// 사용자 디바이스의 위치 서비스가 활성화 상태인지 확인하는 메서드 호출
checkUserDeviceLocationServiceAuthorization()
}
}
사용방법
// 아이폰 위도 및 경도 정보를 주기적으로 받을 수 있는 Closer
LocationService.shared.locationClosur = { [weak self] (latitude, longitude) in
log(direction: .ETC, ofType: self, datas: "위도 : \(latitude)","경도 : \(longitude)")
// 계속 정보를 받을 경우 주석 처리하면 된다.
LocationService.shared.stopLocationUpdate()
}
// 현채 위치의 위도 및 경도를 이용해서 상세 주소를 가져온다.
LocationService.shared.getLocationAddress {[weak self] address in
guard let address = address else {
return
}
log(direction: .ETC, ofType: self, datas: "상세주소 : \(address)")
}
'Swift > 기타' 카테고리의 다른 글
[SWIFT]Contraints 코드로 활성화 비활성화 제어하기 (0) | 2023.04.24 |
---|---|
[SWIFT]NotificationCenter 사용 (0) | 2023.04.24 |
[SWIFT]갤러리 및 카메라 사용 UIImagePickerController(디폴트 UI) (0) | 2023.04.20 |
[SWIFT]네트워크 상태체크 (0) | 2023.04.18 |
[SWIFT]AppVersion 및 번들아이디 정보확인 (0) | 2023.04.18 |