Created
August 10, 2022 00:33
-
-
Save carlynorama/fc01612ff6606dd7afa453d5828319f1 to your computer and use it in GitHub Desktop.
Working on Setting Location
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)) | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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