Weather-SwiftUI icon indicating copy to clipboard operation
Weather-SwiftUI copied to clipboard

Feature: User-Specified Location

Open contirobert opened this issue 5 years ago • 4 comments

Add a custom feature that allows the user to specify the location (by zip code). If the user does not specify a location, the default should remain New York City.

contirobert avatar Jun 13 '19 04:06 contirobert

I built in using core location to your project with the following.

LocationViewModel.swift

import Foundation

struct LocationViewModel {
    var mylatitude: Double?
    var mylongitude: Double?
    var myLocation: String?

    init() {
        self.mylatitude = 43.2012
        self.mylongitude = -88.1087
        self.myLocation = "Germantown"
    }
    
    init(model: CurrentLocaiton) {
        self.mylatitude = model.mylatitude
        self.myLocation = model.myLocation
        self.mylongitude = model.mylongitude
    }
}

CurrentLocaiton.swift

import Foundation

struct CurrentLocaiton {
    var mylatitude: Double?
    var mylongitude: Double?
    var myLocation: String?
    
    init() {
        self.mylatitude = 43.2012
        self.mylongitude = -88.1087
        self.myLocation = "Germantown"
    }
}

LocationService.swift

import CoreLocation
import Combine

class LocationService: NSObject {
    var didChange = PassthroughSubject<LocationService, Never>()
    var locationModel = LocationViewModel()
    var newestLocatoin: ((CLLocationCoordinate2D?) -> Void)?
    var statusUpdated: ((CLAuthorizationStatus) -> Void)?
    var lat: Double?
    var long: Double?
    let manager: CLLocationManager
    
    var status: CLAuthorizationStatus {
        return CLLocationManager.authorizationStatus()
    }
    
    init(manager: CLLocationManager = CLLocationManager()) {
        self.manager = manager
        super.init()
        manager.delegate = self
    }
    
    func getPermission() {
        manager.requestWhenInUseAuthorization()
    }
    
    func getLocation() {
        manager.requestLocation()
    }
}

extension LocationService: CLLocationManagerDelegate {
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        if let location = locations.sorted(by: {$0.timestamp > $1.timestamp} ).first {
            self.newestLocatoin?(location.coordinate)
            locationModel.mylatitude = location.coordinate.latitude
            locationModel.mylongitude = location.coordinate.longitude
            let geoCoder = CLGeocoder()
            geoCoder.reverseGeocodeLocation(location, completionHandler: {
                (placemarks, error) -> Void in
                let placeArray = placemarks as [CLPlacemark]?
                var placeMark: CLPlacemark!
                placeMark = placeArray?[0]
                print(placeMark.locality!)
                self.locationModel.myLocation = placeMark.locality
            })
            
        } else {
            self.newestLocatoin?(nil)
        }
    }
    
    func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
        print("Failed to get ther user location: \(error.localizedDescription)")
    }
    
    func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
        print("Location status: \(status)")
        self.statusUpdated?(status)
    }
}

In Coordinate.swift changed static var newYorkCity: Coordinate {

    static var newYorkCity: Coordinate {
        let locationModel = LocationViewModel()
        if locationModel.mylatitude != nil {
            return Coordinate(latitude: locationModel.mylatitude!, longitude: locationModel.mylongitude!)
        } else  {
            return Coordinate(latitude: 43.2012, longitude: -88.1087)
        }
    }

Network Manager Added

    var currentLocation = LocationViewModel() {
        didSet {
            didChange.send(self)
        }
    }

HeaderView Added

let locationModel = LocationViewModel()
And changed 

Text("(locationModel.myLocation ?? "None")").font(.title).fontWeight(.light).color(.black)

In AppDelgate made the following changes

 let locationService = LocationService()

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        // Location service callbacks
        locationService.newestLocatoin = { [weak self] coordinate in
            guard let _ = self, let coordinate = coordinate else { return }
            print("Location is: \(coordinate)")
        }
        
        switch locationService.status {
        case .notDetermined:
            locationService.getPermission()
        case .authorizedWhenInUse:
            locationService.getLocation()
        default:
            assertionFailure("Location is: \(locationService.status)")
        }
        return true
    }

Hope this is helpful. The project is looking good and a great place for others to start with learning SwiftUI.

mwcs01 avatar Jul 08 '19 02:07 mwcs01

@mwcs01 this is great! Did you want to submit a pull request?

contirobert avatar Jul 12 '19 19:07 contirobert

I have found an issue that I am trying to fix first.

mwcs01 avatar Jul 16 '19 00:07 mwcs01

help me please i'm new in delovper this first project

Semsemq avatar Jun 23 '23 21:06 Semsemq