Skip to content

Commit

Permalink
Fix Realm object has been deleted or invalidated error
Browse files Browse the repository at this point in the history
  • Loading branch information
pawelmilek committed Dec 13, 2023
1 parent e32c882 commit 65272f6
Show file tree
Hide file tree
Showing 11 changed files with 58 additions and 38 deletions.
4 changes: 2 additions & 2 deletions SwiftyForecast Widget/Provider/WeatherProvider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -41,7 +41,7 @@ struct WeatherProvider: TimelineProvider {
}

func getTimeline(in context: Context, completion: @escaping (Timeline<WeatherEntry>) -> Void) {
Task {
Task(priority: .userInitiated) {
let result = await loadWeatherDataForCurrentLocation()
let now = Date.now

Expand Down
12 changes: 6 additions & 6 deletions SwiftyForecast.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion SwiftyForecast/RealmManager/PreviewRealmManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}

Expand Down
4 changes: 2 additions & 2 deletions SwiftyForecast/RealmManager/RealmManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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<LocationModel>
func readAllSorted() throws -> Results<LocationModel>
func update(_ location: LocationModel) throws
Expand Down Expand Up @@ -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)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 1 addition & 2 deletions SwiftyForecast/Screens/Main/MainViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 4 additions & 2 deletions SwiftyForecast/Screens/Main/WeatherViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down

0 comments on commit 65272f6

Please sign in to comment.