Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
1
1weather
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Dmitriy Stepanets
1weather
Commits
2cfcb142
Commit
2cfcb142
authored
Apr 06, 2021
by
Demid Merzlyakov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Storage: CoreData: saving and loading works.
parent
a760d66e
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
56 additions
and
19 deletions
+56
-19
1Weather/Model/LocationManager.swift
+19
-3
1Weather/Storage/CoreData/CoreDataStorage.swift
+23
-4
1Weather/Storage/CoreData/CoreDataUtils.swift
+2
-1
1Weather/Storage/CoreData/Objects/Human/CoreCurrentWeather.swift
+4
-4
1Weather/Storage/CoreData/Objects/Human/CoreDailyWeather.swift
+4
-4
1Weather/Storage/CoreData/Objects/Human/CoreHourlyWeather.swift
+1
-1
1Weather/Storage/CoreData/Objects/Human/CoreLocation.swift
+2
-1
1Weather/Storage/Storage.swift
+1
-1
No files found.
1Weather/Model/LocationManager.swift
View file @
2cfcb142
...
@@ -21,6 +21,7 @@ public class LocationManager {
...
@@ -21,6 +21,7 @@ public class LocationManager {
private
let
weatherUpdateSource
:
WeatherSource
private
let
weatherUpdateSource
:
WeatherSource
private
let
healthSource
:
HealthSource
private
let
healthSource
:
HealthSource
private
let
storage
:
Storage
private
var
defaultLocation
=
Location
(
deviceLocation
:
false
,
private
var
defaultLocation
=
Location
(
deviceLocation
:
false
,
coordinates
:
.
init
(
latitude
:
37.3230
,
longitude
:
-
122.0322
),
// Cupertino
coordinates
:
.
init
(
latitude
:
37.3230
,
longitude
:
-
122.0322
),
// Cupertino
timeZone
:
TimeZone
(
abbreviation
:
"PST"
)
!
)
{
timeZone
:
TimeZone
(
abbreviation
:
"PST"
)
!
)
{
...
@@ -61,7 +62,7 @@ public class LocationManager {
...
@@ -61,7 +62,7 @@ public class LocationManager {
guard
let
self
=
self
else
{
return
}
guard
let
self
=
self
else
{
return
}
delegate
.
locationManager
(
self
,
updatedLocationsList
:
self
.
locations
)
delegate
.
locationManager
(
self
,
updatedLocationsList
:
self
.
locations
)
}
}
storage
.
save
(
locations
:
locations
,
selectedIndex
:
selectedLocationIndex
)
}
}
}
}
...
@@ -125,14 +126,29 @@ public class LocationManager {
...
@@ -125,14 +126,29 @@ public class LocationManager {
}
}
}
}
public
static
let
shared
=
LocationManager
(
weatherUpdateSource
:
WdtWeatherSource
(),
healthSource
:
BlendHealthSource
())
public
static
let
shared
=
LocationManager
(
weatherUpdateSource
:
WdtWeatherSource
(),
healthSource
:
BlendHealthSource
()
,
storage
:
CoreDataStorage
()
)
public
let
maxLocationsCount
=
12
public
let
maxLocationsCount
=
12
public
init
(
weatherUpdateSource
:
WeatherSource
,
healthSource
:
HealthSource
)
{
public
init
(
weatherUpdateSource
:
WeatherSource
,
healthSource
:
HealthSource
,
storage
:
Storage
)
{
self
.
weatherUpdateSource
=
weatherUpdateSource
self
.
weatherUpdateSource
=
weatherUpdateSource
self
.
healthSource
=
healthSource
self
.
healthSource
=
healthSource
self
.
deviceLocationMonitor
=
DeviceLocationMonitor
()
self
.
deviceLocationMonitor
=
DeviceLocationMonitor
()
self
.
storage
=
storage
self
.
deviceLocationMonitor
.
delegate
=
self
self
.
deviceLocationMonitor
.
delegate
=
self
storage
.
load
{
[
weak
self
]
(
locations
,
selectedIndex
,
error
)
in
guard
let
self
=
self
else
{
return
}
guard
error
==
nil
else
{
self
.
log
.
error
(
"Error while loading locations:
\(
error
!
)
"
)
return
}
guard
let
locations
=
locations
else
{
assertionFailure
(
"Either error or locations have to be nil, not both"
)
return
}
self
.
locations
=
locations
self
.
selectedLocationIndex
=
selectedIndex
}
}
}
public
func
updateAllWeatherIfNeeded
()
{
public
func
updateAllWeatherIfNeeded
()
{
...
...
1Weather/Storage/CoreData/CoreDataStorage.swift
View file @
2cfcb142
...
@@ -9,7 +9,7 @@ import Foundation
...
@@ -9,7 +9,7 @@ import Foundation
import
CoreData
import
CoreData
public
class
CoreDataStorage
:
Storage
{
public
class
CoreDataStorage
:
Storage
{
private
let
log
=
Logger
(
componentName
:
"CoreDataStorage"
)
private
let
log
=
Logger
(
componentName
:
"CoreDataStorage
💾
"
)
private
lazy
var
managedContext
:
NSManagedObjectContext
?
=
{
private
lazy
var
managedContext
:
NSManagedObjectContext
?
=
{
persistentContainer
.
newBackgroundContext
()
persistentContainer
.
newBackgroundContext
()
}()
}()
...
@@ -23,7 +23,8 @@ public class CoreDataStorage: Storage {
...
@@ -23,7 +23,8 @@ public class CoreDataStorage: Storage {
return
container
return
container
}()
}()
public
func
save
(
locations
:
[
Location
],
selectedIndex
:
Int
)
{
public
func
save
(
locations
:
[
Location
],
selectedIndex
:
Int
?)
{
log
.
info
(
"Save: start"
)
managedContext
?
.
perform
{
[
weak
self
]
in
managedContext
?
.
perform
{
[
weak
self
]
in
guard
let
self
=
self
else
{
return
}
guard
let
self
=
self
else
{
return
}
guard
let
context
=
self
.
managedContext
else
{
guard
let
context
=
self
.
managedContext
else
{
...
@@ -36,20 +37,28 @@ public class CoreDataStorage: Storage {
...
@@ -36,20 +37,28 @@ public class CoreDataStorage: Storage {
context
.
insert
(
coreAppData
)
context
.
insert
(
coreAppData
)
try
self
.
save
(
context
:
context
)
try
self
.
save
(
context
:
context
)
}
}
self
.
log
.
info
(
"Save: success"
)
}
}
catch
{
catch
{
self
.
log
.
error
(
"
Error during saving
:
\(
error
)
"
)
self
.
log
.
error
(
"
Save: error
:
\(
error
)
"
)
}
}
}
}
}
}
public
func
load
(
completion
:
@escaping
StorageCompletion
)
{
public
func
load
(
completion
:
@escaping
StorageCompletion
)
{
log
.
info
(
"Load: start"
)
managedContext
?
.
perform
{
[
weak
self
]
in
managedContext
?
.
perform
{
[
weak
self
]
in
guard
let
self
=
self
else
{
return
}
guard
let
self
=
self
else
{
return
}
guard
let
context
=
self
.
managedContext
else
{
guard
let
context
=
self
.
managedContext
else
{
return
return
}
}
let
completionOnMain
:
StorageCompletion
=
{
(
locations
,
selectedIndex
,
error
)
in
let
completionOnMain
:
StorageCompletion
=
{
[
weak
self
]
(
locations
,
selectedIndex
,
error
)
in
if
error
!=
nil
{
self
?
.
log
.
error
(
"Load: error."
)
}
else
{
self
?
.
log
.
info
(
"Load: success.
\(
String
(
describing
:
locations
?
.
count
)
)
locations, selected:
\(
String
(
describing
:
selectedIndex
)
)
"
)
}
DispatchQueue
.
main
.
async
{
DispatchQueue
.
main
.
async
{
completion
(
locations
,
selectedIndex
,
error
)
completion
(
locations
,
selectedIndex
,
error
)
}
}
...
@@ -73,19 +82,29 @@ public class CoreDataStorage: Storage {
...
@@ -73,19 +82,29 @@ public class CoreDataStorage: Storage {
}
}
private
func
deleteAll
(
in
context
:
NSManagedObjectContext
)
throws
{
private
func
deleteAll
(
in
context
:
NSManagedObjectContext
)
throws
{
log
.
debug
(
"Delete: start"
)
let
fetchRequest
:
NSFetchRequest
<
CoreAppData
>
=
CoreAppData
.
fetchRequest
()
let
fetchRequest
:
NSFetchRequest
<
CoreAppData
>
=
CoreAppData
.
fetchRequest
()
let
appDataObjects
=
try
context
.
fetch
(
fetchRequest
)
let
appDataObjects
=
try
context
.
fetch
(
fetchRequest
)
if
appDataObjects
.
count
>
1
{
if
appDataObjects
.
count
>
1
{
log
.
warning
(
"Somehow we ended up with more than 1 CoreAppData objects in the DB... deleting them all."
)
log
.
warning
(
"Somehow we ended up with more than 1 CoreAppData objects in the DB... deleting them all."
)
}
}
if
appDataObjects
.
count
>
0
{
log
.
debug
(
"Delete:
\(
appDataObjects
.
count
)
objects..."
)
}
for
appData
in
appDataObjects
{
for
appData
in
appDataObjects
{
context
.
delete
(
appData
)
context
.
delete
(
appData
)
}
}
log
.
info
(
"Delete: success"
)
}
}
private
func
save
(
context
:
NSManagedObjectContext
)
throws
{
private
func
save
(
context
:
NSManagedObjectContext
)
throws
{
log
.
info
(
"Context save: start"
)
if
context
.
hasChanges
{
if
context
.
hasChanges
{
try
context
.
save
()
try
context
.
save
()
log
.
info
(
"Context save: success"
)
}
else
{
log
.
info
(
"Context save: no need"
)
}
}
}
}
}
}
1Weather/Storage/CoreData/CoreDataUtils.swift
View file @
2cfcb142
...
@@ -68,7 +68,8 @@ struct CoreDataUtils {
...
@@ -68,7 +68,8 @@ struct CoreDataUtils {
return
result
return
result
}
}
public
static
func
appValue
<
T
>
(
name
:
String
,
value
:
T
.
RawValue
?,
in
entity
:
Any
)
throws
->
T
?
where
T
:
RawRepresentable
{
// I tried calling it just appValue, so that Swift would figure out wether to use this one or non-optional one, but it gets stuck in infinite recursion in this method occasionally.
public
static
func
appValueOptional
<
T
>
(
name
:
String
,
value
:
T
.
RawValue
?,
in
entity
:
Any
)
throws
->
T
?
where
T
:
RawRepresentable
{
guard
let
value
=
value
else
{
guard
let
value
=
value
else
{
return
nil
return
nil
}
}
...
...
1Weather/Storage/CoreData/Objects/Human/CoreCurrentWeather.swift
View file @
2cfcb142
...
@@ -14,7 +14,7 @@ open class CoreCurrentWeather: _CoreCurrentWeather, CoreDataAppModelConvertable
...
@@ -14,7 +14,7 @@ open class CoreCurrentWeather: _CoreCurrentWeather, CoreDataAppModelConvertable
result
.
minTemp
=
try
CoreDataUtils
.
measurement
(
from
:
self
.
minTemp
,
in
:
self
,
attributeName
:
"minTemp"
)
result
.
minTemp
=
try
CoreDataUtils
.
measurement
(
from
:
self
.
minTemp
,
in
:
self
,
attributeName
:
"minTemp"
)
result
.
maxTemp
=
try
CoreDataUtils
.
measurement
(
from
:
self
.
maxTemp
,
in
:
self
,
attributeName
:
"maxTemp"
)
result
.
maxTemp
=
try
CoreDataUtils
.
measurement
(
from
:
self
.
maxTemp
,
in
:
self
,
attributeName
:
"maxTemp"
)
result
.
windSpeed
=
try
CoreDataUtils
.
measurement
(
from
:
self
.
windSpeed
,
in
:
self
,
attributeName
:
"windSpeed"
)
result
.
windSpeed
=
try
CoreDataUtils
.
measurement
(
from
:
self
.
windSpeed
,
in
:
self
,
attributeName
:
"windSpeed"
)
result
.
windDirection
=
try
CoreDataUtils
.
appValue
(
name
:
"windDirection"
,
value
:
self
.
windDirection
,
in
:
self
)
result
.
windDirection
=
try
CoreDataUtils
.
appValue
Optional
(
name
:
"windDirection"
,
value
:
self
.
windDirection
,
in
:
self
)
if
let
precipProb
=
self
.
precipitationProbability
{
if
let
precipProb
=
self
.
precipitationProbability
{
result
.
precipitationProbability
=
Percent
(
precipProb
.
uintValue
)
result
.
precipitationProbability
=
Percent
(
precipProb
.
uintValue
)
}
}
...
@@ -29,12 +29,12 @@ open class CoreCurrentWeather: _CoreCurrentWeather, CoreDataAppModelConvertable
...
@@ -29,12 +29,12 @@ open class CoreCurrentWeather: _CoreCurrentWeather, CoreDataAppModelConvertable
result
.
sunrise
=
self
.
sunrise
result
.
sunrise
=
self
.
sunrise
result
.
sunset
=
self
.
sunset
result
.
sunset
=
self
.
sunset
result
.
sunState
=
try
CoreDataUtils
.
appValue
(
name
:
"sunState"
,
value
:
self
.
sunState
,
in
:
self
)
result
.
sunState
=
try
CoreDataUtils
.
appValue
Optional
(
name
:
"sunState"
,
value
:
self
.
sunState
,
in
:
self
)
result
.
moonrise
=
self
.
moonrise
result
.
moonrise
=
self
.
moonrise
result
.
moonset
=
self
.
moonset
result
.
moonset
=
self
.
moonset
result
.
approximateMoonrise
=
self
.
approximateMoonrise
result
.
approximateMoonrise
=
self
.
approximateMoonrise
result
.
moonState
=
try
CoreDataUtils
.
appValue
(
name
:
"moonState"
,
value
:
self
.
moonState
,
in
:
self
)
result
.
moonState
=
try
CoreDataUtils
.
appValue
Optional
(
name
:
"moonState"
,
value
:
self
.
moonState
,
in
:
self
)
result
.
moonPhase
=
try
CoreDataUtils
.
appValue
(
name
:
"moonPhase"
,
value
:
self
.
moonPhase
,
in
:
self
)
result
.
moonPhase
=
try
CoreDataUtils
.
appValue
Optional
(
name
:
"moonPhase"
,
value
:
self
.
moonPhase
,
in
:
self
)
return
result
return
result
}
}
...
...
1Weather/Storage/CoreData/Objects/Human/CoreDailyWeather.swift
View file @
2cfcb142
...
@@ -15,19 +15,19 @@ open class CoreDailyWeather: _CoreDailyWeather, CoreDataAppModelConvertable {
...
@@ -15,19 +15,19 @@ open class CoreDailyWeather: _CoreDailyWeather, CoreDataAppModelConvertable {
result
.
minTemp
=
try
CoreDataUtils
.
measurement
(
from
:
self
.
minTemp
,
in
:
self
,
attributeName
:
"minTemp"
)
result
.
minTemp
=
try
CoreDataUtils
.
measurement
(
from
:
self
.
minTemp
,
in
:
self
,
attributeName
:
"minTemp"
)
result
.
maxTemp
=
try
CoreDataUtils
.
measurement
(
from
:
self
.
maxTemp
,
in
:
self
,
attributeName
:
"maxTemp"
)
result
.
maxTemp
=
try
CoreDataUtils
.
measurement
(
from
:
self
.
maxTemp
,
in
:
self
,
attributeName
:
"maxTemp"
)
result
.
windSpeed
=
try
CoreDataUtils
.
measurement
(
from
:
self
.
windSpeed
,
in
:
self
,
attributeName
:
"windSpeed"
)
result
.
windSpeed
=
try
CoreDataUtils
.
measurement
(
from
:
self
.
windSpeed
,
in
:
self
,
attributeName
:
"windSpeed"
)
result
.
windDirection
=
try
CoreDataUtils
.
appValue
(
name
:
"windDirection"
,
value
:
self
.
windDirection
,
in
:
self
)
result
.
windDirection
=
try
CoreDataUtils
.
appValue
Optional
(
name
:
"windDirection"
,
value
:
self
.
windDirection
,
in
:
self
)
if
let
precipProb
=
self
.
precipitationProbability
{
if
let
precipProb
=
self
.
precipitationProbability
{
result
.
precipitationProbability
=
Percent
(
precipProb
.
uintValue
)
result
.
precipitationProbability
=
Percent
(
precipProb
.
uintValue
)
}
}
result
.
sunrise
=
self
.
sunrise
result
.
sunrise
=
self
.
sunrise
result
.
sunset
=
self
.
sunset
result
.
sunset
=
self
.
sunset
result
.
sunState
=
try
CoreDataUtils
.
appValue
(
name
:
"sunState"
,
value
:
self
.
sunState
,
in
:
self
)
result
.
sunState
=
try
CoreDataUtils
.
appValue
Optional
(
name
:
"sunState"
,
value
:
self
.
sunState
,
in
:
self
)
result
.
moonrise
=
self
.
moonrise
result
.
moonrise
=
self
.
moonrise
result
.
moonset
=
self
.
moonset
result
.
moonset
=
self
.
moonset
result
.
moonState
=
try
CoreDataUtils
.
appValue
(
name
:
"moonState"
,
value
:
self
.
moonState
,
in
:
self
)
result
.
moonState
=
try
CoreDataUtils
.
appValue
Optional
(
name
:
"moonState"
,
value
:
self
.
moonState
,
in
:
self
)
result
.
moonPhase
=
try
CoreDataUtils
.
appValue
(
name
:
"moonPhase"
,
value
:
self
.
moonPhase
,
in
:
self
)
result
.
moonPhase
=
try
CoreDataUtils
.
appValue
Optional
(
name
:
"moonPhase"
,
value
:
self
.
moonPhase
,
in
:
self
)
return
result
return
result
}
}
...
...
1Weather/Storage/CoreData/Objects/Human/CoreHourlyWeather.swift
View file @
2cfcb142
...
@@ -15,7 +15,7 @@ open class CoreHourlyWeather: _CoreHourlyWeather, CoreDataAppModelConvertable {
...
@@ -15,7 +15,7 @@ open class CoreHourlyWeather: _CoreHourlyWeather, CoreDataAppModelConvertable {
result
.
apparentTemp
=
try
CoreDataUtils
.
measurement
(
from
:
self
.
apparentTemp
,
in
:
self
,
attributeName
:
"apparentTemp"
)
result
.
apparentTemp
=
try
CoreDataUtils
.
measurement
(
from
:
self
.
apparentTemp
,
in
:
self
,
attributeName
:
"apparentTemp"
)
result
.
windSpeed
=
try
CoreDataUtils
.
measurement
(
from
:
self
.
windSpeed
,
in
:
self
,
attributeName
:
"windSpeed"
)
result
.
windSpeed
=
try
CoreDataUtils
.
measurement
(
from
:
self
.
windSpeed
,
in
:
self
,
attributeName
:
"windSpeed"
)
result
.
windDirection
=
try
CoreDataUtils
.
appValue
(
name
:
"windDirection"
,
value
:
self
.
windDirection
,
in
:
self
)
result
.
windDirection
=
try
CoreDataUtils
.
appValue
Optional
(
name
:
"windDirection"
,
value
:
self
.
windDirection
,
in
:
self
)
if
let
precipProb
=
self
.
precipitationProbability
{
if
let
precipProb
=
self
.
precipitationProbability
{
result
.
precipitationProbability
=
Percent
(
precipProb
.
uintValue
)
result
.
precipitationProbability
=
Percent
(
precipProb
.
uintValue
)
}
}
...
...
1Weather/Storage/CoreData/Objects/Human/CoreLocation.swift
View file @
2cfcb142
...
@@ -47,6 +47,7 @@ open class CoreLocation: _CoreLocation, CoreDataAppModelConvertable {
...
@@ -47,6 +47,7 @@ open class CoreLocation: _CoreLocation, CoreDataAppModelConvertable {
return
nil
return
nil
}
}
self
.
init
(
managedObjectContext
:
context
)
self
.
init
(
managedObjectContext
:
context
)
self
.
deviceLocation
=
appModel
.
deviceLocation
self
.
lastWeatherUpdateDate
=
appModel
.
lastWeatherUpdateDate
self
.
lastWeatherUpdateDate
=
appModel
.
lastWeatherUpdateDate
if
let
coordinates
=
appModel
.
coordinates
{
if
let
coordinates
=
appModel
.
coordinates
{
...
@@ -61,7 +62,7 @@ open class CoreLocation: _CoreLocation, CoreDataAppModelConvertable {
...
@@ -61,7 +62,7 @@ open class CoreLocation: _CoreLocation, CoreDataAppModelConvertable {
self
.
nickname
=
appModel
.
nickname
self
.
nickname
=
appModel
.
nickname
self
.
zip
=
appModel
.
zip
self
.
zip
=
appModel
.
zip
self
.
fipsCode
=
appModel
.
fipsCode
self
.
fipsCode
=
appModel
.
fipsCode
self
.
timeZone
=
try
CoreDataUtils
.
timeZoneToString
(
appModel
.
timeZone
,
in
:
self
,
attributeName
:
"timeZone"
)
self
.
today
=
skipIfError
(
attribute
:
"today"
,
action
:
{
try
CoreCurrentWeather
(
context
:
context
,
appModel
:
appModel
.
today
)})
self
.
today
=
skipIfError
(
attribute
:
"today"
,
action
:
{
try
CoreCurrentWeather
(
context
:
context
,
appModel
:
appModel
.
today
)})
...
...
1Weather/Storage/Storage.swift
View file @
2cfcb142
...
@@ -10,6 +10,6 @@ import Foundation
...
@@ -10,6 +10,6 @@ import Foundation
public
typealias
StorageCompletion
=
([
Location
]?,
Int
?,
Error
?)
->
()
public
typealias
StorageCompletion
=
([
Location
]?,
Int
?,
Error
?)
->
()
public
protocol
Storage
{
public
protocol
Storage
{
func
save
(
locations
:
[
Location
],
selectedIndex
:
Int
)
func
save
(
locations
:
[
Location
],
selectedIndex
:
Int
?
)
func
load
(
completion
:
@escaping
StorageCompletion
)
func
load
(
completion
:
@escaping
StorageCompletion
)
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment