I’m a beginner, trying to get the latitude and longitude from LocationManager and show it in the ContentView using SwiftUI but result showing nil. But the console prints the data from LocationManager class. Not showing the latitude and longitude from the content view. Can anyone help? (Xcode 11)
This is the LocationManager class
import Foundation
import CoreLocation
import Combine
class LocationManager: NSObject,CLLocationManagerDelegate, ObservableObject {
private let manager: CLLocationManager
var willChange = PassthroughSubject<LocationManager, Never>()
var getLat: String = ""
var getLon: String = ""
var lastKnownLocation: CLLocation? {
willSet {
willChange.send(self)
}
}
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
if status == .denied {
print("denied")
}
else{
print("athorized")
manager.requestLocation()
}
}
func start() {
manager.requestWhenInUseAuthorization()
manager.startUpdatingLocation()
}
init(manager: CLLocationManager = CLLocationManager()) {
self.manager = manager
super.init()
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print(error.localizedDescription)
}
func startUpdating() {
self.manager.delegate = self
self.manager.requestWhenInUseAuthorization()
self.manager.startUpdatingLocation()
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
//print(locations)
lastKnownLocation = locations.last
getLat = "\(locations.last!.coordinate.latitude)"
getLon = "\(locations.last!.coordinate.longitude)"
showLocation()
}
func showLocation() {
print("from showLocation")
print("Latitude: \(getLat)")
print("Longitude: \(getLon)")
}
}
This is the console that shows the latitude and longitude from LocationManager class
This is the Content View
import SwiftUI
import CoreLocation
struct ContentView: View {
@State var managerDelegate = LocationManager()
@State var manager = CLLocationManager()
@ObservedObject var location = LocationManager()
var lat: String {
return "\(location.lastKnownLocation?.coordinate.latitude ?? 0.0)"
}
var lon: String {
return "\(location.lastKnownLocation?.coordinate.longitude ?? 0.0)"
}
init() {
self.manager.delegate = self.managerDelegate
do {
try self.manager.requestAlwaysAuthorization()
}
catch {
print(error.localizedDescription)
self.manager.requestAlwaysAuthorization()
}
}
var body: some View {
VStack {
Text("Hello, World")
Text("Latitude: \(lat)")
Text("Longitude: \(lon)")
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Alright, I found myself the time to read your code and I have a solution for you.
First, you'll want to set the delegate to the variable that you are observing, inside ContentView.init()
:
self.manager.delegate = self.location
Immediately after, you'll want to call the startUpdating()
function that you defined in LocationManager
:
self.location.startUpdating()
Finally, you may want to remove your will-change
implementation and opt for the more simple:
@Published var lastKnownLocation: CLLocation?
The published wrapper will automatically trigger object changes for you.
Now if you like, you can also reduce your init statement down to one line:
init() {
self.location.startUpdating()
}
Which means you can freely remove a couple properties:
`@State var managerDelegate = LocationManager()`
`@State var manager = CLLocationManager()`
TLDR; Here is a shortened version of the code:
The content view
import SwiftUI
struct ContentView: View {
@ObservedObject var location = LocationManager()
var lat: String {
return "\(location.lastKnownLocation?.coordinate.latitude ?? 0.0)"
}
var lon: String {
return "\(location.lastKnownLocation?.coordinate.longitude ?? 0.0)"
}
init() {
self.location.startUpdating()
}
var body: some View {
VStack {
Text("Location breakdown")
Text("Latitude: \(lat)")
Text("Longitude: \(lon)")
}
.padding()
.padding()
.background(Color.white)
.cornerRadius(10)
.shadow(radius: 10)
}
}
The Location Manager
import Foundation
import CoreLocation
class LocationManager: NSObject, CLLocationManagerDelegate, ObservableObject {
private let manager = CLLocationManager()
@Published var lastKnownLocation: CLLocation?
func startUpdating() {
self.manager.delegate = self
self.manager.requestWhenInUseAuthorization()
self.manager.startUpdatingLocation()
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
lastKnownLocation = locations.last
}
}