diff --git a/SwiftyForecast Widget/Provider/WeatherProvider.swift b/SwiftyForecast Widget/Provider/WeatherProvider.swift index 2c746ff4..916d03fc 100644 --- a/SwiftyForecast Widget/Provider/WeatherProvider.swift +++ b/SwiftyForecast Widget/Provider/WeatherProvider.swift @@ -23,7 +23,7 @@ struct WeatherProvider: TimelineProvider { } func getSnapshot(in context: Context, completion: @escaping (WeatherEntry) -> Void) { - Task { + Task(priority: .userInitiated) { let result = await loadWeatherDataForCurrentLocation() let now = Date.now @@ -41,7 +41,7 @@ struct WeatherProvider: TimelineProvider { } func getTimeline(in context: Context, completion: @escaping (Timeline) -> Void) { - Task { + Task(priority: .userInitiated) { let result = await loadWeatherDataForCurrentLocation() let now = Date.now diff --git a/SwiftyForecast.xcodeproj/project.pbxproj b/SwiftyForecast.xcodeproj/project.pbxproj index 94f89a22..1ad0d226 100644 --- a/SwiftyForecast.xcodeproj/project.pbxproj +++ b/SwiftyForecast.xcodeproj/project.pbxproj @@ -752,22 +752,22 @@ isa = PBXGroup; children = ( E23997DC20E84129007D8CE4 /* Application */, + E24E90572ADA7DF8009255C8 /* Screens */, + E21ABD3F2AE8269900F93F01 /* Views */, + E23997DA20E84104007D8CE4 /* Models */, + E270891824CE5904003F7587 /* Coordinator */, + E23997D720E84094007D8CE4 /* Storyboards */, + E23997DF20E84371007D8CE4 /* Network */, E25EF00A20F97CE200E4C115 /* Style.swift */, E20DA45A214348AD0047491B /* NetworkReachabilityManager.swift */, E283573B2B2728AA00E3807A /* RealmManager */, E28357342B27168400E3807A /* LocationManager */, E2A32F25254459DF000ACEFE /* AppStoreReview */, - E21ABD3F2AE8269900F93F01 /* Views */, - E270891824CE5904003F7587 /* Coordinator */, E2435BD322AD6293007589CE /* Measurement */, - E23997DF20E84371007D8CE4 /* Network */, E28357332B27150D00E3807A /* Modifiers */, E23997DD20E84158007D8CE4 /* Extensions */, E23997E520E84371007D8CE4 /* Errors */, E21A0B9420EE88F5006AC409 /* Utilities */, - E24E90572ADA7DF8009255C8 /* Screens */, - E23997DA20E84104007D8CE4 /* Models */, - E23997D720E84094007D8CE4 /* Storyboards */, E23997D820E840C1007D8CE4 /* Resources */, ); path = SwiftyForecast; diff --git a/SwiftyForecast/RealmManager/PreviewRealmManager.swift b/SwiftyForecast/RealmManager/PreviewRealmManager.swift index 0af72382..c884bdb8 100644 --- a/SwiftyForecast/RealmManager/PreviewRealmManager.swift +++ b/SwiftyForecast/RealmManager/PreviewRealmManager.swift @@ -38,7 +38,7 @@ final class PreviewRealmManager: DatabaseManager { } } - func read(by primaryKey: String) throws -> LocationModel? { + func readBy(primaryKey: String) throws -> LocationModel? { return previewRealm.object(ofType: LocationModel.self, forPrimaryKey: primaryKey) } diff --git a/SwiftyForecast/RealmManager/RealmManager.swift b/SwiftyForecast/RealmManager/RealmManager.swift index 82e3ddac..6c5de2aa 100644 --- a/SwiftyForecast/RealmManager/RealmManager.swift +++ b/SwiftyForecast/RealmManager/RealmManager.swift @@ -3,7 +3,7 @@ import RealmSwift protocol DatabaseManager { func create(_ location: LocationModel) throws - func read(by primaryKey: String) throws -> LocationModel? + func readBy(primaryKey: String) throws -> LocationModel? func readAll() throws -> Results func readAllSorted() throws -> Results func update(_ location: LocationModel) throws @@ -51,7 +51,7 @@ extension RealmManager { } } - func read(by primaryKey: String) throws -> LocationModel? { + func readBy(primaryKey: String) throws -> LocationModel? { return realm.object(ofType: LocationModel.self, forPrimaryKey: primaryKey) } diff --git a/SwiftyForecast/Screens/LocationSearch/LocationCurrentWeather/LocationWeatherView+ViewModel.swift b/SwiftyForecast/Screens/LocationSearch/LocationCurrentWeather/LocationWeatherView+ViewModel.swift index 69f7e43f..d34e87b2 100644 --- a/SwiftyForecast/Screens/LocationSearch/LocationCurrentWeather/LocationWeatherView+ViewModel.swift +++ b/SwiftyForecast/Screens/LocationSearch/LocationCurrentWeather/LocationWeatherView+ViewModel.swift @@ -73,7 +73,7 @@ extension LocationWeatherView { private func verifyLocationExistanceInDatabase(_ location: LocationModel) { do { - if try databaseManager.read(by: location.compoundKey) != nil { + if try databaseManager.readBy(primaryKey: location.compoundKey) != nil { isExistingLocation = true } else { isExistingLocation = false diff --git a/SwiftyForecast/Screens/LocationSearch/LocationCurrentWeather/LocationWeatherView.swift b/SwiftyForecast/Screens/LocationSearch/LocationCurrentWeather/LocationWeatherView.swift index 03c8f45b..4b26e334 100644 --- a/SwiftyForecast/Screens/LocationSearch/LocationCurrentWeather/LocationWeatherView.swift +++ b/SwiftyForecast/Screens/LocationSearch/LocationCurrentWeather/LocationWeatherView.swift @@ -76,7 +76,7 @@ struct LocationWeatherView: View { } .onChange(of: viewModel.locationModel) { guard let locationModel = viewModel.locationModel else { return } - cardViewModel.loadWeather(at: locationModel) + cardViewModel.setLocationModel(locationModel) } .onChange(of: viewModel.isExistingLocation) { toolbarAddItemOpacity = viewModel.isExistingLocation == true ? 0.0 : 1.0 diff --git a/SwiftyForecast/Screens/Main/MainViewController.swift b/SwiftyForecast/Screens/Main/MainViewController.swift index 69ba45f8..4b93b2ef 100644 --- a/SwiftyForecast/Screens/Main/MainViewController.swift +++ b/SwiftyForecast/Screens/Main/MainViewController.swift @@ -74,8 +74,7 @@ private extension MainViewController { locationManager.$error .compactMap { $0 } .sink { error in -// AlertViewPresenter.shared.presentError(withMessage: error.localizedDescription) - // TODO: Use Apple Logger to log error description + debugPrint(error.localizedDescription) } .store(in: &cancellables) diff --git a/SwiftyForecast/Screens/Main/ViewModel/WeatherViewController+ViewModel.swift b/SwiftyForecast/Screens/Main/ViewModel/WeatherViewController+ViewModel.swift index beb97df6..21524104 100644 --- a/SwiftyForecast/Screens/Main/ViewModel/WeatherViewController+ViewModel.swift +++ b/SwiftyForecast/Screens/Main/ViewModel/WeatherViewController+ViewModel.swift @@ -68,22 +68,26 @@ extension WeatherViewController { .store(in: &cancellables) } + func reloadCurrentLocation() { + guard locationModel != nil else { return } + do { + self.locationModel = try RealmManager.shared.readAllSorted().first(where: { $0.name == locationName }) + } catch { + fatalError(error.localizedDescription) + } + } + func loadData() { guard let locationModel else { return } guard !isLoading else { return } isLoading = true - let locationCoordinate = CLLocationCoordinate2D( - latitude: locationModel.latitude, - longitude: locationModel.longitude - ) + let latitude = locationModel.latitude + let longitude = locationModel.longitude Task(priority: .userInitiated) { do { - let forecast = try await service.fetchForecast( - latitude: locationCoordinate.latitude, - longitude: locationCoordinate.longitude - ) + let forecast = try await service.fetchForecast(latitude: latitude, longitude: longitude) let data = ResponseParser.parse(forecast: forecast) weatherModel = data isLoading = false diff --git a/SwiftyForecast/Screens/Main/WeatherViewController.swift b/SwiftyForecast/Screens/Main/WeatherViewController.swift index 7d4d7101..ea8eda1f 100644 --- a/SwiftyForecast/Screens/Main/WeatherViewController.swift +++ b/SwiftyForecast/Screens/Main/WeatherViewController.swift @@ -138,6 +138,7 @@ private extension WeatherViewController { viewModel.$twentyFourHoursForecastModel .combineLatest(viewModel.$fiveDaysForecastModel) + .receive(on: DispatchQueue.main) .map { ($0.0.map { HourlyViewCell.ViewModel(model: $0) }, $0.1.map { DailyViewCell.ViewModel(model: $0) }) } .sink { [self] (hourlyViewModels, dailyViewModels) in hourlyForecastViewModels = hourlyViewModels @@ -152,9 +153,10 @@ private extension WeatherViewController { func subscribeToNotificationCenterPublisher() { NotificationCenter.default .publisher(for: UIApplication.didBecomeActiveNotification) + .receive(on: DispatchQueue.main) .sink { [weak self] _ in - self?.loadData() - self?.weatherCardViewController.loadData() + self?.viewModel?.reloadCurrentLocation() + self?.weatherCardViewController.reloadCurrentLocation() } .store(in: &cancellables) } diff --git a/SwiftyForecast/Views/CurrentWeatherCard/CurrentWeatherCard+ViewModel.swift b/SwiftyForecast/Views/CurrentWeatherCard/CurrentWeatherCard+ViewModel.swift index eefdbbd4..28542374 100644 --- a/SwiftyForecast/Views/CurrentWeatherCard/CurrentWeatherCard+ViewModel.swift +++ b/SwiftyForecast/Views/CurrentWeatherCard/CurrentWeatherCard+ViewModel.swift @@ -47,7 +47,19 @@ extension CurrentWeatherCard { registerMeasurementSystemObserver() } + func setLocationModel(_ locationModel: LocationModel) { + self.locationModel = locationModel + } + private func subscribeToPublisher() { + $locationModel + .compactMap { $0 } + .receive(on: DispatchQueue.main) + .sink { [self] locationModel in + loadData(at: locationModel) + } + .store(in: &cancellables) + $model .compactMap { $0 } .receive(on: DispatchQueue.main) @@ -90,23 +102,26 @@ extension CurrentWeatherCard { setWindSpeedAccordingToMeasurementSystem() } - func loadData() { - guard let locationModel else { return } - loadWeather(at: locationModel) + func reloadCurrentLocation() { + guard locationModel != nil else { return } + do { + self.locationModel = try RealmManager.shared.readAllSorted().first(where: { $0.name == locationName }) + } catch { + fatalError(error.localizedDescription) + } } - func loadWeather(at location: LocationModel) { + func loadData(at locationModel: LocationModel) { guard !isLoading else { return } isLoading = true - locationName = location.name - locationModel = location + + locationName = locationModel.name + let latitude = locationModel.latitude + let longitude = locationModel.longitude Task(priority: .userInitiated) { do { - let currentResponse = try await service.fetchCurrent( - latitude: location.latitude, - longitude: location.longitude - ) + let currentResponse = try await service.fetchCurrent(latitude: latitude, longitude: longitude) let dataModel = ResponseParser.parse(current: currentResponse) let largeIcon = try await service.fetchLargeIcon(symbol: dataModel.icon) icon = Image(uiImage: largeIcon) diff --git a/SwiftyForecast/Views/CurrentWeatherCard/CurrentWeatherCardViewController.swift b/SwiftyForecast/Views/CurrentWeatherCard/CurrentWeatherCardViewController.swift index 9341746e..658ead2c 100644 --- a/SwiftyForecast/Views/CurrentWeatherCard/CurrentWeatherCardViewController.swift +++ b/SwiftyForecast/Views/CurrentWeatherCard/CurrentWeatherCardViewController.swift @@ -22,12 +22,12 @@ final class CurrentWeatherCardViewController: UIViewController { setup() } - func loadData() { - viewModel.loadData() + func reloadCurrentLocation() { + viewModel.reloadCurrentLocation() } func loadData(at location: LocationModel) { - viewModel.loadWeather(at: location) + viewModel.loadData(at: location) } private func setup() {