Skip to content

Commit 1c736ca

Browse files
authored
Merge pull request #53 from TaskarCenterAtUW/feature-fix-user-location
Fix user location
2 parents 8285a86 + d3b0e30 commit 1c736ca

File tree

5 files changed

+119
-59
lines changed

5 files changed

+119
-59
lines changed

GoInfoGame/GoInfoGame.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@
160160
FA87A8172B6AC885000A6BEA /* StepsInclineTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA87A8162B6AC885000A6BEA /* StepsInclineTests.swift */; };
161161
FA87A8192B6B01A4000A6BEA /* HandRailTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA87A8182B6B01A4000A6BEA /* HandRailTests.swift */; };
162162
FA87A81B2B6B042E000A6BEA /* SideWalkWidthTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA87A81A2B6B042E000A6BEA /* SideWalkWidthTests.swift */; };
163+
FABF3CF42B7419BB0080EAC9 /* LocationManagerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = FABF3CF32B7419BB0080EAC9 /* LocationManagerDelegate.swift */; };
163164
FAC9E60F2B04F9C800E2C608 /* OverpassRequestManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAC9E60E2B04F9C800E2C608 /* OverpassRequestManager.swift */; };
164165
FAC9E6112B06811300E2C608 /* LocationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAC9E6102B06811300E2C608 /* LocationManager.swift */; };
165166
FAD5C4F32AFCBE700040C61A /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAD5C4F22AFCBE700040C61A /* AppDelegate.swift */; };
@@ -409,6 +410,7 @@
409410
FA87A8162B6AC885000A6BEA /* StepsInclineTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StepsInclineTests.swift; sourceTree = "<group>"; };
410411
FA87A8182B6B01A4000A6BEA /* HandRailTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HandRailTests.swift; sourceTree = "<group>"; };
411412
FA87A81A2B6B042E000A6BEA /* SideWalkWidthTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SideWalkWidthTests.swift; sourceTree = "<group>"; };
413+
FABF3CF32B7419BB0080EAC9 /* LocationManagerDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationManagerDelegate.swift; sourceTree = "<group>"; };
412414
FAC9E60E2B04F9C800E2C608 /* OverpassRequestManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OverpassRequestManager.swift; sourceTree = "<group>"; };
413415
FAC9E6102B06811300E2C608 /* LocationManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationManager.swift; sourceTree = "<group>"; };
414416
FAD5C4EF2AFCBE700040C61A /* GoInfoGame.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = GoInfoGame.app; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -1055,6 +1057,7 @@
10551057
FAD5C4F42AFCBE700040C61A /* SceneDelegate.swift */,
10561058
FAC9E60E2B04F9C800E2C608 /* OverpassRequestManager.swift */,
10571059
FAC9E6102B06811300E2C608 /* LocationManager.swift */,
1060+
FABF3CF32B7419BB0080EAC9 /* LocationManagerDelegate.swift */,
10581061
05CB71DD2B0FAEC200DED821 /* UI */,
10591062
05CB71DE2B0FAFAA00DED821 /* Bridges */,
10601063
058EADD92B10E02E0017E259 /* DataBase */,
@@ -1577,6 +1580,7 @@
15771580
A4E711A42B57B13100C9DE08 /* QuestionHeader.swift in Sources */,
15781581
973FC0442B59468800878269 /* BusStopLitForm.swift in Sources */,
15791582
971575192B5FFE910044797C /* LocationManagerCoordinator.swift in Sources */,
1583+
FABF3CF42B7419BB0080EAC9 /* LocationManagerDelegate.swift in Sources */,
15801584
973FC0382B59363C00878269 /* TactilePavingSteps.swift in Sources */,
15811585
973FC0192B4FB17000878269 /* LocalizedStrings.swift in Sources */,
15821586
FAC9E6112B06811300E2C608 /* LocationManager.swift in Sources */,

GoInfoGame/GoInfoGame/Base.lproj/Main.storyboard

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,26 @@
44
<dependencies>
55
<deployment identifier="iOS"/>
66
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22504"/>
7+
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
8+
<capability name="System colors in document resources" minToolsVersion="11.0"/>
79
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
810
</dependencies>
911
<scenes>
1012
<!--Map View Controller-->
1113
<scene sceneID="eS8-T4-bVR">
1214
<objects>
1315
<hostingController id="oB8-mI-y0B" customClass="MapViewController" customModule="GoInfoGame" customModuleProvider="target" sceneMemberID="viewController">
16+
<view key="view" contentMode="scaleToFill" id="WIL-R2-Zwd">
17+
<rect key="frame" x="0.0" y="0.0" width="393" height="852"/>
18+
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
19+
<viewLayoutGuide key="safeArea" id="YrN-Z6-zFT"/>
20+
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
21+
</view>
1422
<navigationItem key="navigationItem" id="yQo-Up-QSM"/>
1523
</hostingController>
1624
<placeholder placeholderIdentifier="IBFirstResponder" id="s7U-Gu-uwn" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
1725
</objects>
18-
<point key="canvasLocation" x="305" y="-68"/>
26+
<point key="canvasLocation" x="304.58015267175574" y="-68.309859154929583"/>
1927
</scene>
2028
<!--Navigation Controller-->
2129
<scene sceneID="Oj0-5X-njE">
@@ -39,4 +47,9 @@
3947
<point key="canvasLocation" x="-688" y="-68"/>
4048
</scene>
4149
</scenes>
50+
<resources>
51+
<systemColor name="systemBackgroundColor">
52+
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
53+
</systemColor>
54+
</resources>
4255
</document>
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
//
2+
// LocationManagerDelegate.swift
3+
// GoInfoGame
4+
//
5+
// Created by Achyut Kumar M on 08/02/24.
6+
//
7+
8+
import CoreLocation
9+
import MapKit
10+
11+
class LocationManagerDelegate: NSObject, ObservableObject, CLLocationManagerDelegate {
12+
13+
var locationManager = CLLocationManager()
14+
@Published var location: CLLocation?
15+
var locationUpdateHandler: ((CLLocation) -> Void)?
16+
17+
override init() {
18+
super.init()
19+
}
20+
21+
func requestLocationAuthorization() {
22+
locationManager.requestWhenInUseAuthorization()
23+
}
24+
25+
func startUpdatingLocation() {
26+
DispatchQueue.global(qos: .background).async {
27+
guard CLLocationManager.locationServicesEnabled() else {
28+
print("Location services are not enabled")
29+
return
30+
}
31+
32+
DispatchQueue.main.async {
33+
self.locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
34+
self.locationManager.startUpdatingLocation()
35+
}
36+
}
37+
}
38+
39+
40+
func stopUpdatingLocation() {
41+
locationManager.stopUpdatingLocation()
42+
}
43+
44+
func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
45+
switch manager.authorizationStatus {
46+
case .authorizedWhenInUse:
47+
print("Authorized")
48+
startUpdatingLocation()
49+
case .denied, .restricted:
50+
print("Not Authorized")
51+
default:
52+
print("Requesting authorization...")
53+
requestLocationAuthorization()
54+
}
55+
}
56+
57+
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
58+
guard let mostRecentLocation = locations.last else { return }
59+
location = mostRecentLocation
60+
locationUpdateHandler?(mostRecentLocation)
61+
stopUpdatingLocation()
62+
}
63+
}

GoInfoGame/GoInfoGame/UI/Map/MapView.swift

Lines changed: 9 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -10,32 +10,19 @@ import MapKit
1010
import CoreLocation
1111

1212
struct MapView: View {
13+
14+
@State var trackingMode: MapUserTrackingMode = MapUserTrackingMode.none
15+
@StateObject var locationManagerDelegate = LocationManagerDelegate()
16+
1317
@Environment(\.presentationMode) private var presentationMode
1418
@AppStorage("isMapFromOnboarding") var isMapFromOnboarding: Bool = false
1519
@StateObject private var viewModel = MapViewModel()
16-
@State private var userTrackingMode: MapUserTrackingMode = .none
17-
18-
var btnBack: some View {
19-
Button(action: {
20-
if isMapFromOnboarding {
21-
isMapFromOnboarding = false
22-
NavigationUtil.popToRootView()
23-
} else {
24-
presentationMode.wrappedValue.dismiss()
25-
}
26-
}) {
27-
HStack(spacing: 0) {
28-
Image(systemName: "chevron.left")
29-
.scaleEffect(0.50)
30-
.font(Font.title.weight(.medium))
31-
Text("Back")
32-
}
33-
}
34-
}
35-
20+
3621
var body: some View {
22+
3723
ZStack {
38-
Map(coordinateRegion: $viewModel.coordinateRegion, showsUserLocation: true, userTrackingMode: $userTrackingMode, annotationItems: viewModel.items) { item in
24+
Map(coordinateRegion: $viewModel.region, showsUserLocation: true, userTrackingMode: $trackingMode, annotationItems: viewModel.items) { item in
25+
3926
MapAnnotation(coordinate: item.coordinateInfo) {
4027
Button {
4128
viewModel.selectedQuest = item.displayUnit
@@ -66,12 +53,9 @@ struct MapView: View {
6653
// Nothing here
6754
}
6855
}
69-
.onAppear {
70-
viewModel.fetchData()
71-
}
72-
7356
}
7457
}
58+
7559
#Preview {
7660
MapView()
7761
}

GoInfoGame/GoInfoGame/UI/Map/MapViewModel.swift

Lines changed: 29 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -11,54 +11,49 @@ import MapKit
1111
import CoreLocation
1212

1313
class MapViewModel: ObservableObject {
14-
@Published var coordinateRegion: MKCoordinateRegion = MKCoordinateRegion()
14+
15+
let locationManagerDelegate = LocationManagerDelegate()
16+
17+
var region = MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: 37.3318, longitude: -122.0312), span: MKCoordinateSpan(latitudeDelta: 0.0004 , longitudeDelta: 0.0004 ))
18+
let viewSpanDelta = 0.0004 // Delta lat/lng to show to the user
19+
20+
1521
@Published var items: [DisplayUnitWithCoordinate] = []
1622
@Published var selectedQuest: DisplayUnit?
17-
private let locationManager = LocationManagerCoordinator()
1823
@Published var isLoading: Bool = false
19-
let viewSpanDelta = 0.0004 // Delta lat/lng to show to the user
20-
let dataSpanDistance: CLLocationDistance = 100 // Distance from user location to get the data
21-
24+
let dataSpanDistance: CLLocationDistance = 1000 // Distance from user location to get the data
25+
2226
init() {
23-
// self.coordinateRegion = MKCoordinateRegion()
24-
locationManager.locationUpdateHandler = { [weak self] location in
27+
locationManagerDelegate.locationManager.delegate = locationManagerDelegate
28+
locationManagerDelegate.locationManager.requestWhenInUseAuthorization()
29+
locationManagerDelegate.locationManager.startUpdatingLocation()
30+
31+
locationManagerDelegate.locationUpdateHandler = { [weak self] location in
2532
guard let self = self else { return }
26-
DispatchQueue.main.async {
27-
print("Centering map on location")
28-
self.centerMapOnLocation(location)
29-
}
33+
fetchOSMDataFor(currentLocation: location)
3034
}
35+
36+
}
37+
38+
@objc private func locationDidChange() {
39+
guard let userLocation = locationManagerDelegate.location else { return }
40+
fetchOSMDataFor(currentLocation: userLocation)
3141
}
3242

33-
func fetchData() {
43+
func fetchOSMDataFor(currentLocation: CLLocation) {
3444
isLoading = true
35-
let boundingBox = boundingBoxAroundLocation(location: locationManager.currentLocation ?? CLLocation(latitude: coordinateRegion.center.latitude, longitude: coordinateRegion.center.longitude), distance: dataSpanDistance)
36-
AppQuestManager.shared.fetchData(fromBBOx: boundingBox) { [weak self] in
45+
let bBox = boundingBoxAroundLocation(location: currentLocation, distance: dataSpanDistance)
46+
self.region = MKCoordinateRegion(center: currentLocation.coordinate, span: MKCoordinateSpan(
47+
latitudeDelta: viewSpanDelta,
48+
longitudeDelta: viewSpanDelta
49+
))
50+
AppQuestManager.shared.fetchData(fromBBOx: bBox) { [weak self] in
3751
guard let self = self else { return }
3852
self.items = AppQuestManager.shared.fetchQuestsFromDB()
3953
self.isLoading = false
4054
}
4155
}
42-
43-
func centerMapOnLocation(_ location: CLLocation) {
44-
// Update coordinate region only if necessary
45-
let region = MKCoordinateRegion(center: location.coordinate, span: MKCoordinateSpan(
46-
latitudeDelta: viewSpanDelta,
47-
longitudeDelta: viewSpanDelta
48-
))
4956

50-
if !coordinateRegionIsEqual(region, coordinateRegion) {
51-
coordinateRegion = region
52-
fetchData() // Fetch data when the map region changes
53-
}
54-
}
55-
56-
private func coordinateRegionIsEqual(_ region1: MKCoordinateRegion, _ region2: MKCoordinateRegion) -> Bool {
57-
return region1.center.latitude == region2.center.latitude &&
58-
region1.center.longitude == region2.center.longitude &&
59-
region1.span.latitudeDelta == region2.span.latitudeDelta &&
60-
region1.span.longitudeDelta == region2.span.longitudeDelta
61-
}
6257
private func boundingBoxAroundLocation(location: CLLocation, distance: CLLocationDistance) -> BBox {
6358
let region = MKCoordinateRegion(center: location.coordinate, latitudinalMeters: distance, longitudinalMeters: distance)
6459
let center = region.center
@@ -68,6 +63,7 @@ class MapViewModel: ObservableObject {
6863
let minLon = center.longitude - span.longitudeDelta / 2
6964
let maxLon = center.longitude + span.longitudeDelta / 2
7065

66+
7167
return BBox(minLat: minLat, maxLat: maxLat, minLon: minLon, maxLon: maxLon)
7268
}
7369
}

0 commit comments

Comments
 (0)