Görkem Aydın
Görkem Aydın

Reputation: 175

How to get Current Location with SwiftUI?

Trying to get current location with using swiftUI. Below code, couldn't initialize with didUpdateLocations delegate.

class GetLocation : BindableObject {
    var didChange = PassthroughSubject<GetLocation,Never>()

    var location : CLLocation {
        didSet {
            didChange.send(self)
        }
    }
    init() {}
}

Upvotes: 13

Views: 9155

Answers (3)

lsrggr
lsrggr

Reputation: 429

I have written a one-file swift package with usage instructions on https://github.com/himbeles/LocationProvider. It provides a ObservableObject-type wrapper class for CLLocationManager and its delegate. There is a @Published property location which can directly be used in SwiftUI, as well as a PassthroughSubject<CLLocation, Never> called locationWillChange that you can subscribe to via Combine. Both update on every didUpdateLocations event of the CLLocationManager.

It also handles the case where location access has previously been denied: The default behavior is to present the user with a request to enable access in the app settings and a link to go there.

In SwiftUI (> iOS 14, > macOS 11), use as

import SwiftUI
import LocationProvider

struct ContentView: View {
    @StateObject var locationProvider = LocationProvider()
    
    var body: some View {
        VStack{
            Text("latitude \(locationProvider.location?.coordinate.latitude ?? 0)")
            Text("longitude \(locationProvider.location?.coordinate.longitude ?? 0)")
        }
        .onAppear {
            do {try locationProvider.start()} 
            catch {
                print("No location access.")
                locationProvider.requestAuthorization()
            }
        }
    }
}

Upvotes: 5

Viktor Gardart
Viktor Gardart

Reputation: 4490

This code below works (Not production ready). Implementing the CLLocationManagerDelegate works fine and the lastKnownLocation is updated accordingly.

Don't forget to set the NSLocationWhenInUseUsageDescription in your Info.plist

class LocationManager: NSObject, ObservableObject, CLLocationManagerDelegate {
    private let manager = CLLocationManager()
    var lastKnownLocation: CLLocation?

    func startUpdating() {
        manager.delegate = self
        manager.requestWhenInUseAuthorization()
        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()
        }
    }
}

Upvotes: 8

MwcsMac
MwcsMac

Reputation: 7168

As of Xcode 11 beta 4, you will need to change didChange to willChange:

var willChange = PassthroughSubject<LocationManager, Never>()

var lastKnownLocation: CLLocation? {
    willSet {
        willChange.send(self)
    }
}

Upvotes: 3

Related Questions