Skip to content

Instantly share code, notes, and snippets.

@carlynorama
Created August 10, 2022 00:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save carlynorama/fc01612ff6606dd7afa453d5828319f1 to your computer and use it in GitHub Desktop.
Save carlynorama/fc01612ff6606dd7afa453d5828319f1 to your computer and use it in GitHub Desktop.
Working on Setting Location
import SwiftUI
import CoreLocationUI
struct LocationPickerView: View {
@StateObject var locationManager = LocationManager()
@State private var locationName:String = ""
var body: some View {
Form {
if let location = locationManager.location?.coordinate {
Text("Your location: \(location.latitude), \(location.longitude)")
Text("Locality name: \(locationManager.locality ?? "...")")
} else {
Text("No location set.")
}
Section {
HStack {
TextField("Location", text: $locationName)
CurrentLocationButton()
}
}
}.task(id: locationManager.locality) {
pushLocalityChange()
}
.environmentObject(locationManager)
}
func pushLocalityChange() {
locationName = locationManager.locality ?? ""
}
}
struct CurrentLocationButton: View {
@EnvironmentObject var locationManager:LocationManager
var body: some View {
if #available(iOS 15.0, *) {
LocationButton(.currentLocation) {
locationManager.requestLocation()
}.symbolVariant(.fill)
.labelStyle(.iconOnly)
.foregroundColor(Color.white)
.cornerRadius(20)
.font(.system(size:12))
}
}
}
//
// LocationService.swift
// Wind
//
// Created by Labtanza on 8/9/22.
//
import Foundation
import CoreLocation
protocol LocationService:ObservableObject {
var currentLocation:CLLocation { get }
var locationPublisher:Published<CLLocation>.Publisher { get }
var locationPublished: Published<CLLocation> { get }
func updateLocation(lat:Double, long:Double)
}
extension LocationService {
// public func updateLocation(lat:Double, long:Double) {
// currentLocation = CLLocation(latitude: lat, longitude: long)
// }
var currentLatitude:Double { currentLocation.coordinate.latitude }
var currentLongitude:Double { currentLocation.coordinate.longitude }
var currentDescription:String? {
get async throws {
try await Self.lookUpPlacemark(for: self.currentLocation).locality
}
}
static func lookUpPlacemark(for location:CLLocation) async throws -> CLPlacemark {
let result = try await CLGeocoder().reverseGeocodeLocation(location)
let firstLocation = result[0]
return firstLocation
}
}
//MARK: LocationService+Location
struct Location {
let latitude:Double
let longitude:Double
let description:String
}
extension LocationService {
var currentLocationInfo:Location {
Location(latitude: currentLatitude, longitude: currentLongitude, description: "None")
}
}
class LocationManager: NSObject, ObservableObject {
let manager = CLLocationManager()
@Published var location:CLLocation?
@Published var locality:String?
override init() {
super.init()
manager.delegate = self
manager.desiredAccuracy = kCLLocationAccuracyReduced
manager.requestWhenInUseAuthorization()
}
}
extension LocationManager:CLLocationManagerDelegate {
var isEnabled:Bool? {
switch manager.authorizationStatus {
case .restricted, .denied:
return false
case .authorizedWhenInUse, .authorizedAlways:
return true
case .notDetermined: // The user hasn’t chosen an authorization status
return nil
@unknown default:
fatalError()
}
}
func locationManager(_ manager: CLLocationManager,
didChangeAuthorization status: CLAuthorizationStatus) {
switch status {
case .notDetermined : print("notDetermined") // location permission not asked for yet
case .authorizedWhenInUse : print("authorizedWhenInUse") // location authorized
case .authorizedAlways : print("authorizedAlways") // location authorized
case .restricted : print("restricted") // TODO: handle
case .denied : print("denied") // TODO: handle
@unknown default : fatalError()
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
location = locations.first//?.coordinate
updateLocality()
}
func locationManager(_ manager: CLLocationManager, didFailWithError error:Error) {
print("Error requesting location")
}
func requestLocation() {
manager.requestLocation()
}
}
extension LocationManager {
func placemarkForLocation(_ location:CLLocation) async throws -> CLPlacemark {
let result = try await CLGeocoder().reverseGeocodeLocation(location)
let firstLocation = result[0]
return firstLocation
}
func locationForString(_ addressString:String) async throws -> CLLocation? {
let result = try await CLGeocoder().geocodeAddressString(addressString)
let firstPlaceMark = result[0]
return firstPlaceMark.location
//func geocodeAddressString(_ addressString: String) async throws -> [CLPlacemark]
}
func updateLocality() {
Task {
if let loc = location {
do {
let placemark = try await placemarkForLocation(loc)
DispatchQueue.main.async {
self.locality = placemark.locality
}
} catch {
print("LM updateLocality: couldn't find locality")
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment