forked from maplibre/maplibre-native
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
User Location and Location Privacy Example iOS (maplibre#2389)
- Loading branch information
Showing
13 changed files
with
298 additions
and
34 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
# User Location & Location Privacy | ||
|
||
Requesting precise location with ``MLNLocationManager``. | ||
|
||
## Overview | ||
|
||
This example shows how to request a precise location with ``MLNLocationManager``. | ||
|
||
First of all you need to prepare your `Info.plist`. You need to provide a description why your app needs to access location: | ||
|
||
```plist | ||
<key>NSLocationWhenInUseUsageDescription</key> | ||
<string>Dummy Location When In Use Description</string> | ||
``` | ||
|
||
As well as a description why your app needs precise location. | ||
|
||
```plist | ||
<key>NSLocationTemporaryUsageDescriptionDictionary</key> | ||
<dict> | ||
<key>MLNAccuracyAuthorizationDescription</key> | ||
<string>Dummy Precise Location Description</string> | ||
</dict> | ||
``` | ||
|
||
The `Coordinator` defined below is also the ``MLNMapViewDelegate``. When the location manager authorization changes it will call the relevant method. If precise location has not been granted, a button is shown at the bottom of the map. | ||
|
||
![](ImpreciseLocation.png) | ||
|
||
When the button is pressed a pop-up with the description we set in `Info.plist` will be shown: | ||
|
||
![](PreciseLocationRequestPopup.png) | ||
|
||
<!-- include-example(LocationPrivacyExample) --> | ||
|
||
```swift | ||
enum LocationAccuracyState { | ||
case unknown | ||
case reducedAccuracy | ||
case fullAccuracy | ||
} | ||
|
||
class Coordinator: NSObject, MLNMapViewDelegate { | ||
@Binding var mapView: MLNMapView | ||
@Binding var locationAccuracy: LocationAccuracyState | ||
var pannedToUserLocation = false | ||
|
||
init(mapView: Binding<MLNMapView>, locationAccuracy: Binding<LocationAccuracyState>) { | ||
_mapView = mapView | ||
_locationAccuracy = locationAccuracy | ||
} | ||
|
||
func mapView(_: MLNMapView, didChangeLocationManagerAuthorization manager: MLNLocationManager) { | ||
guard let accuracySetting = manager.accuracyAuthorization else { | ||
return | ||
} | ||
|
||
switch accuracySetting() { | ||
case .fullAccuracy: | ||
locationAccuracy = .fullAccuracy | ||
case .reducedAccuracy: | ||
locationAccuracy = .reducedAccuracy | ||
@unknown default: | ||
locationAccuracy = .unknown | ||
} | ||
} | ||
|
||
// when a location is available for the first time, we fly to it | ||
func mapView(_ mapView: MLNMapView, didUpdate _: MLNUserLocation?) { | ||
if pannedToUserLocation { | ||
return | ||
} | ||
guard let userLocation = mapView.userLocation else { | ||
print("User location is currently not available.") | ||
return | ||
} | ||
mapView.fly(to: MLNMapCamera(lookingAtCenter: userLocation.coordinate, altitude: 100_000, pitch: 0, heading: 0)) | ||
} | ||
} | ||
|
||
struct LocationPrivacyExample: UIViewRepresentable { | ||
@Binding var mapView: MLNMapView | ||
@Binding var locationAccuracy: LocationAccuracyState | ||
|
||
func makeCoordinator() -> Coordinator { | ||
Coordinator(mapView: $mapView, locationAccuracy: $locationAccuracy) | ||
} | ||
|
||
func makeUIView(context: Context) -> MLNMapView { | ||
let mapView = MLNMapView() | ||
mapView.showsUserLocation = true | ||
mapView.delegate = context.coordinator | ||
|
||
return mapView | ||
} | ||
|
||
func updateUIView(_: MLNMapView, context _: Context) {} | ||
} | ||
|
||
struct LocationPrivacyExampleView: View { | ||
@State private var mapView = MLNMapView() | ||
@State var locationAccuracy: LocationAccuracyState = .unknown | ||
|
||
var body: some View { | ||
VStack { | ||
LocationPrivacyExample(mapView: $mapView, locationAccuracy: $locationAccuracy) | ||
.edgesIgnoringSafeArea(.all) | ||
|
||
if locationAccuracy == LocationAccuracyState.reducedAccuracy { | ||
Button("Request Precise Location") { | ||
handleButtonPress(mapView: mapView) | ||
} | ||
.padding() | ||
.background(Color.blue) | ||
.foregroundColor(.white) | ||
.cornerRadius(8) | ||
} | ||
} | ||
} | ||
|
||
private func handleButtonPress(mapView: MLNMapView) { | ||
print("Requesting precice location") | ||
switch locationAccuracy { | ||
case .reducedAccuracy: | ||
let purposeKey = "MLNAccuracyAuthorizationDescription" | ||
mapView.locationManager.requestTemporaryFullAccuracyAuthorization!(withPurposeKey: purposeKey) | ||
default: | ||
break | ||
} | ||
} | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
102 changes: 102 additions & 0 deletions
102
platform/ios/app-swift/Sources/LocationPrivacyExample.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
import MapLibre | ||
import SwiftUI | ||
import UIKit | ||
|
||
// #-example-code(LocationPrivacyExample) | ||
enum LocationAccuracyState { | ||
case unknown | ||
case reducedAccuracy | ||
case fullAccuracy | ||
} | ||
|
||
class Coordinator: NSObject, MLNMapViewDelegate { | ||
@Binding var mapView: MLNMapView | ||
@Binding var locationAccuracy: LocationAccuracyState | ||
var pannedToUserLocation = false | ||
|
||
init(mapView: Binding<MLNMapView>, locationAccuracy: Binding<LocationAccuracyState>) { | ||
_mapView = mapView | ||
_locationAccuracy = locationAccuracy | ||
} | ||
|
||
func mapView(_: MLNMapView, didChangeLocationManagerAuthorization manager: MLNLocationManager) { | ||
guard let accuracySetting = manager.accuracyAuthorization else { | ||
return | ||
} | ||
|
||
switch accuracySetting() { | ||
case .fullAccuracy: | ||
locationAccuracy = .fullAccuracy | ||
case .reducedAccuracy: | ||
locationAccuracy = .reducedAccuracy | ||
@unknown default: | ||
locationAccuracy = .unknown | ||
} | ||
} | ||
|
||
// when a location is available for the first time, we fly to it | ||
func mapView(_ mapView: MLNMapView, didUpdate _: MLNUserLocation?) { | ||
if pannedToUserLocation { | ||
return | ||
} | ||
guard let userLocation = mapView.userLocation else { | ||
print("User location is currently not available.") | ||
return | ||
} | ||
mapView.fly(to: MLNMapCamera(lookingAtCenter: userLocation.coordinate, altitude: 100_000, pitch: 0, heading: 0)) | ||
} | ||
} | ||
|
||
struct LocationPrivacyExample: UIViewRepresentable { | ||
@Binding var mapView: MLNMapView | ||
@Binding var locationAccuracy: LocationAccuracyState | ||
|
||
func makeCoordinator() -> Coordinator { | ||
Coordinator(mapView: $mapView, locationAccuracy: $locationAccuracy) | ||
} | ||
|
||
func makeUIView(context: Context) -> MLNMapView { | ||
let mapView = MLNMapView() | ||
mapView.showsUserLocation = true | ||
mapView.delegate = context.coordinator | ||
|
||
return mapView | ||
} | ||
|
||
func updateUIView(_: MLNMapView, context _: Context) {} | ||
} | ||
|
||
struct LocationPrivacyExampleView: View { | ||
@State private var mapView = MLNMapView() | ||
@State var locationAccuracy: LocationAccuracyState = .unknown | ||
|
||
var body: some View { | ||
VStack { | ||
LocationPrivacyExample(mapView: $mapView, locationAccuracy: $locationAccuracy) | ||
.edgesIgnoringSafeArea(.all) | ||
|
||
if locationAccuracy == LocationAccuracyState.reducedAccuracy { | ||
Button("Request Precise Location") { | ||
handleButtonPress(mapView: mapView) | ||
} | ||
.padding() | ||
.background(Color.blue) | ||
.foregroundColor(.white) | ||
.cornerRadius(8) | ||
} | ||
} | ||
} | ||
|
||
private func handleButtonPress(mapView: MLNMapView) { | ||
print("Requesting precice location") | ||
switch locationAccuracy { | ||
case .reducedAccuracy: | ||
let purposeKey = "MLNAccuracyAuthorizationDescription" | ||
mapView.locationManager.requestTemporaryFullAccuracyAuthorization!(withPurposeKey: purposeKey) | ||
default: | ||
break | ||
} | ||
} | ||
} | ||
|
||
// #-end-example-code |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
20 changes: 20 additions & 0 deletions
20
platform/ios/app-swift/Sources/MapLibreNavigationView.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import MapLibre | ||
import SwiftUI | ||
|
||
struct MapLibreNavigationView: View { | ||
var body: some View { | ||
NavigationStack { | ||
List { | ||
NavigationLink("SimpleMap") { | ||
SimpleMap().edgesIgnoringSafeArea(.all) | ||
} | ||
NavigationLink("LineTapMap") { | ||
LineTapMap().edgesIgnoringSafeArea(.all) | ||
} | ||
NavigationLink("LocationPrivacyExample") { | ||
LocationPrivacyExampleView() | ||
} | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.