Essayer d'obtenir l'emplacement actuel en utilisant swiftUI. Sous le code, impossible d'initialiser avec le délégué didUpdateLocations.
class GetLocation : BindableObject {
var didChange = PassthroughSubject<GetLocation,Never>()
var location : CLLocation {
didSet {
didChange.send(self)
}
}
init() {}
}
Ce code ci-dessous fonctionne (pas prêt pour la production). L'implémentation de CLLocationManagerDelegate
fonctionne correctement et le lastKnownLocation
est mis à jour en conséquence.
N'oubliez pas de définir le NSLocationWhenInUseUsageDescription
dans votre Info.plist
class LocationManager: NSObject, CLLocationManagerDelegate, BindableObject {
private let manager: CLLocationManager
var didChange = PassthroughSubject<LocationManager, Never>()
var lastKnownLocation: CLLocation? {
didSet {
didChange.send(self)
}
}
init(manager: CLLocationManager = CLLocationManager()) {
self.manager = manager
super.init()
}
func startUpdating() {
self.manager.delegate = self
self.manager.requestWhenInUseAuthorization()
self.manager.startUpdatingLocation()
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
print(locations)
lastKnownLocation = locations.last
}
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
if status == .authorizedWhenInUse {
manager.startUpdatingLocation()
}
}
}
À partir de Xcode 11 beta 4, vous devrez remplacer didChange
par willChange
:
var willChange = PassthroughSubject<LocationManager, Never>()
var lastKnownLocation: CLLocation? {
willSet {
willChange.send(self)
}
}
J'ai écrit un fichier unique Swift avec des instructions d'utilisation sur https://github.com/himbeles/LocationProvider . Il fournit un ObservableObject
de type wrapper pour CLLocationManager et son délégué. Il existe une propriété publiée location
qui peut être directement utilisée dans SwiftUI, ainsi qu'un PassthroughSubject auquel vous pouvez vous abonner via Combine. Les deux sont mis à jour sur chaque didUpdateLocations
événement du CLLocationManager.
Il gère également le cas où l'accès à l'emplacement a été précédemment refusé: le comportement par défaut consiste à présenter à l'utilisateur une demande d'activation de l'accès dans les paramètres de l'application et un lien pour y accéder.
Dans SwiftUI, utilisez comme
import SwiftUI
import LocationProvider
struct ContentView: View {
@ObservedObject var locationProvider : LocationProvider
init() {
locationProvider = LocationProvider()
do {try locationProvider.start()}
catch {
print("No location access.")
locationProvider.requestAuthorization()
}
}
var body: some View {
VStack{
Text("latitude \(locationProvider.location?.coordinate.latitude ?? 0)")
Text("longitude \(locationProvider.location?.coordinate.longitude ?? 0)")
}
}
}