diff --git a/MC2Maps.xcodeproj/project.pbxproj b/MC2Maps.xcodeproj/project.pbxproj index f9cfb53..3b4f4ac 100644 --- a/MC2Maps.xcodeproj/project.pbxproj +++ b/MC2Maps.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + A88329EE2C6DEBCC00D6CC87 /* MapLocation.swift in Sources */ = {isa = PBXBuildFile; fileRef = A88329ED2C6DEBCC00D6CC87 /* MapLocation.swift */; }; EAF2746D2C1C6B2C00D90AEA /* MC2MapsApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAF2746C2C1C6B2C00D90AEA /* MC2MapsApp.swift */; }; EAF2746F2C1C6B2C00D90AEA /* MapsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAF2746E2C1C6B2C00D90AEA /* MapsView.swift */; }; EAF274712C1C6B2E00D90AEA /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = EAF274702C1C6B2E00D90AEA /* Assets.xcassets */; }; @@ -14,6 +15,7 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + A88329ED2C6DEBCC00D6CC87 /* MapLocation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapLocation.swift; sourceTree = ""; }; EAF274692C1C6B2C00D90AEA /* MC2Maps.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MC2Maps.app; sourceTree = BUILT_PRODUCTS_DIR; }; EAF2746C2C1C6B2C00D90AEA /* MC2MapsApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MC2MapsApp.swift; sourceTree = ""; }; EAF2746E2C1C6B2C00D90AEA /* MapsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapsView.swift; sourceTree = ""; }; @@ -55,6 +57,7 @@ EAF5A4462C22D14600EA2907 /* Info.plist */, EAF2746C2C1C6B2C00D90AEA /* MC2MapsApp.swift */, EAF2746E2C1C6B2C00D90AEA /* MapsView.swift */, + A88329ED2C6DEBCC00D6CC87 /* MapLocation.swift */, EAF274702C1C6B2E00D90AEA /* Assets.xcassets */, EAF274722C1C6B2E00D90AEA /* Preview Content */, ); @@ -141,6 +144,7 @@ files = ( EAF2746F2C1C6B2C00D90AEA /* MapsView.swift in Sources */, EAF2746D2C1C6B2C00D90AEA /* MC2MapsApp.swift in Sources */, + A88329EE2C6DEBCC00D6CC87 /* MapLocation.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/MC2Maps.xcodeproj/project.xcworkspace/xcuserdata/evelyn.xcuserdatad/UserInterfaceState.xcuserstate b/MC2Maps.xcodeproj/project.xcworkspace/xcuserdata/evelyn.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000..1c67745 Binary files /dev/null and b/MC2Maps.xcodeproj/project.xcworkspace/xcuserdata/evelyn.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/MC2Maps.xcodeproj/xcuserdata/evelyn.xcuserdatad/xcschemes/xcschememanagement.plist b/MC2Maps.xcodeproj/xcuserdata/evelyn.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..228afd0 --- /dev/null +++ b/MC2Maps.xcodeproj/xcuserdata/evelyn.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,14 @@ + + + + + SchemeUserState + + MC2Maps.xcscheme_^#shared#^_ + + orderHint + 0 + + + + diff --git a/MC2Maps/MapLocation.swift b/MC2Maps/MapLocation.swift new file mode 100644 index 0000000..b215ba3 --- /dev/null +++ b/MC2Maps/MapLocation.swift @@ -0,0 +1,46 @@ +// +// Maplocation.swift +// MC2Maps +// +// Created by Evelyn Hong on 8/15/24. +// + +import SwiftUI +import CoreLocation + +final class GeoServiceManager: NSObject, CLLocationManagerDelegate { + private var locationManager: CLLocationManager! + + override init() { + super.init() + locationManager = CLLocationManager() + locationManager.delegate = self + locationManager.desiredAccuracy = kCLLocationAccuracyBest + locationManager.startUpdatingLocation() + } + + // 좌표 -> 도로명 주소 + func getRoadAddress(for location: CLLocation, completion: @escaping (String?) -> Void) { + let geocoder = CLGeocoder() + let locale = Locale(identifier: "Ko-kr") + geocoder.reverseGeocodeLocation(location, preferredLocale: locale) { placeMarks, error in + guard let placeMarks = placeMarks, + let address = placeMarks.last, + error == nil else { + completion(nil) // 오류 발생 시 nil 반환 + return + } + let country = address.country ?? "" + let administrativeArea = address.administrativeArea ?? "" + let locality = address.locality ?? "" + let subLocality = address.subLocality ?? "" + let subThoroughfare = address.subThoroughfare ?? "" + let fullAddress = "\(country) \(administrativeArea) \(locality) \(subLocality) \(subThoroughfare)" + + + DispatchQueue.main.async { + completion(fullAddress) // 주소 문자열을 반환 + } + } + } +} diff --git a/MC2Maps/MapsView.swift b/MC2Maps/MapsView.swift index e9943c7..e46274c 100644 --- a/MC2Maps/MapsView.swift +++ b/MC2Maps/MapsView.swift @@ -9,6 +9,7 @@ import SwiftUI import MapKit import CoreLocation + // 커스텀 어노테이션 구조체 생성 struct AnnotationItem: Identifiable, Equatable{ let id = UUID() @@ -36,8 +37,12 @@ struct MapsView: View { @State private var baseLocation : CLLocationCoordinate2D? // baseLocation을 현재위치로 사용 @State private var specialAnnotationCounter = 0//스페셜한 어노테이션 수 - @State private var selectedSpecialAnnotation: AnnotationItem? // 선택된 어노테이션(선택시 업데이트;sheet를 통해 모달 올리기) + @State private var selectedSpecialAnnotation: AnnotationItem? = nil // 선택된 어노테이션(선택시 업데이트;sheet를 통해 모달 올리기) + @State private var roadAddress: String? = nil + + let geoServiceManager = GeoServiceManager() + let maxAnnotations = 48 // 최대 어노테이션 수 let gridSize = 6 let cellSize = 0.0001 @@ -51,7 +56,7 @@ struct MapsView: View { .resizable() .frame(width: 25, height: 25) .scaleEffect(selectedSpecialAnnotation == annotation ? 2.0 : 1.0) - .rotationEffect(Angle(degrees: selectedSpecialAnnotation == annotation ? 10 : 0)) + .rotationEffect(Angle(degrees: selectedSpecialAnnotation == annotation ? 10 : 0)) .animation(.interpolatingSpring(mass: 2, stiffness: 80, damping: 10, initialVelocity: 0)) .onTapGesture { withAnimation() { @@ -111,6 +116,19 @@ struct MapsView: View { } Text("북: \(annotation.coordinate.latitude)") Text("동: \(annotation.coordinate.longitude)") + // 도로명 주소 표시 + if let roadAddress = roadAddress { + Text("주소: \(roadAddress)") + } else { + Text("주소를 불러오는 중...") + .onAppear { + let location = CLLocation(latitude: annotation.coordinate.latitude, + longitude: annotation.coordinate.longitude) + geoServiceManager.getRoadAddress(for: location) { address in + self.roadAddress = address + } + } + } Text("오늘은 이곳에서 00만큼 머물렀습니다") Button("Close") { selectedSpecialAnnotation = nil @@ -175,20 +193,22 @@ struct MapsView: View { class LocationManager: NSObject, ObservableObject, CLLocationManagerDelegate { var locationManager = CLLocationManager() @Published var location: CLLocation? - + override init() { super.init() self.locationManager.delegate = self self.locationManager.requestWhenInUseAuthorization() self.locationManager.startUpdatingLocation() self.locationManager.allowsBackgroundLocationUpdates = true //백그라운드에서 동작 - + } - + func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { guard let location = locations.last else { return } self.location = location } + + } struct ContentView_Previews: PreviewProvider {