How to get Current Location using SwiftUI, without ViewControllers?

前端 未结 1 932
甜味超标
甜味超标 2021-01-30 09:39

I\'ve prepared in my project the following class to retrieve the user current location:

LocationManager.swift

import Foundation
import CoreLocation


class Loca         


        
1条回答
  •  醉梦人生
    2021-01-30 09:58

    You could create an ObservedObject of your LocationManager by implementing the ObservableObject protocol.

    With the @Published attribute you can create a publisher object which notify the observers (your view, in this case) when something changes inside that object.

    That's why in my LocationManager I added the @Published attribute to those var:

    1. locationStatus: CLAuthorizationStatus? it contains the value received from didChangeAuthorization delegate method
    2. lastLocation: CLLocation? it contains the last location calculated by the didUpdateLocations delegate method

    LocationManager

    import Foundation
    import CoreLocation
    import Combine
    
    class LocationManager: NSObject, ObservableObject {
    
        override init() {
            super.init()
            self.locationManager.delegate = self
            self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
            self.locationManager.requestWhenInUseAuthorization()
            self.locationManager.startUpdatingLocation()
        }
    
        @Published var locationStatus: CLAuthorizationStatus? {
            willSet {
                objectWillChange.send()
            }
        }
    
        @Published var lastLocation: CLLocation? {
            willSet {
                objectWillChange.send()
            }
        }
    
        var statusString: String {
            guard let status = locationStatus else {
                return "unknown"
            }
    
            switch status {
            case .notDetermined: return "notDetermined"
            case .authorizedWhenInUse: return "authorizedWhenInUse"
            case .authorizedAlways: return "authorizedAlways"
            case .restricted: return "restricted"
            case .denied: return "denied"
            default: return "unknown"
            }
    
        }
    
        let objectWillChange = PassthroughSubject()
    
        private let locationManager = CLLocationManager()
    }
    
    extension LocationManager: CLLocationManagerDelegate {
    
        func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
            self.locationStatus = status
            print(#function, statusString)
        }
    
        func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
            guard let location = locations.last else { return }
            self.lastLocation = location
            print(#function, location)
        }
    
    }
    

    View

    In your view you need to create only an instance of LocationManager marked as @ObservedObject

    import SwiftUI
    
    struct MyView: View {
    
        @ObservedObject var locationManager = LocationManager()
    
        var userLatitude: String {
            return "\(locationManager.lastLocation?.coordinate.latitude ?? 0)"
        }
    
        var userLongitude: String {
            return "\(locationManager.lastLocation?.coordinate.longitude ?? 0)"
        }
    
        var body: some View {
            VStack {
                Text("location status: \(locationManager.statusString)")
                HStack {
                    Text("latitude: \(userLatitude)")
                    Text("longitude: \(userLongitude)")
                }
            }
        }
    }
    
    struct MyView_Previews: PreviewProvider {
        static var previews: some View {
            MyView()
        }
    }
    

    0 讨论(0)
提交回复
热议问题