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
a760d66e
Commit
a760d66e
authored
Apr 06, 2021
by
Demid Merzlyakov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Storage: CoreData: CoreDataStorage implementation.
parent
ea42db8c
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
100 additions
and
25 deletions
+100
-25
1Weather.xcodeproj/project.pbxproj
+4
-0
1Weather/Storage/CoreData/1WModel.xcdatamodeld/Model.xcdatamodel/contents
+1
-1
1Weather/Storage/CoreData/CoreDataStorage.swift
+48
-19
1Weather/Storage/CoreData/Objects/AppData.swift
+15
-0
1Weather/Storage/CoreData/Objects/Human/CoreAppData.swift
+29
-2
1Weather/Storage/CoreData/Objects/Machine/_CoreAppData.swift
+1
-1
1Weather/Storage/Storage.swift
+2
-2
No files found.
1Weather.xcodeproj/project.pbxproj
View file @
a760d66e
...
@@ -150,6 +150,7 @@
...
@@ -150,6 +150,7 @@
CE9F01BB261B31A6009BA500
/* CoreDataError.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CE9F01BA261B31A6009BA500
/* CoreDataError.swift */
;
};
CE9F01BB261B31A6009BA500
/* CoreDataError.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CE9F01BA261B31A6009BA500
/* CoreDataError.swift */
;
};
CE9F01BE261B34C0009BA500
/* CoreDataAppModelConvertable.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CE9F01BD261B34C0009BA500
/* CoreDataAppModelConvertable.swift */
;
};
CE9F01BE261B34C0009BA500
/* CoreDataAppModelConvertable.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CE9F01BD261B34C0009BA500
/* CoreDataAppModelConvertable.swift */
;
};
CE9F01C1261B3776009BA500
/* CoreDataUtils.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CE9F01C0261B3776009BA500
/* CoreDataUtils.swift */
;
};
CE9F01C1261B3776009BA500
/* CoreDataUtils.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CE9F01C0261B3776009BA500
/* CoreDataUtils.swift */
;
};
CE9F01CC261C9A6E009BA500
/* AppData.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CE9F01CB261C9A6D009BA500
/* AppData.swift */
;
};
CEAD00A12577B2D5003596AD
/* StuffThatIsPresentInTheMainProject.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CEAD00A02577B2D5003596AD
/* StuffThatIsPresentInTheMainProject.swift */
;
};
CEAD00A12577B2D5003596AD
/* StuffThatIsPresentInTheMainProject.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CEAD00A02577B2D5003596AD
/* StuffThatIsPresentInTheMainProject.swift */
;
};
CEAFF08325DFC67F00DF4EBF
/* Location.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CEAFF08225DFC67F00DF4EBF
/* Location.swift */
;
};
CEAFF08325DFC67F00DF4EBF
/* Location.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CEAFF08225DFC67F00DF4EBF
/* Location.swift */
;
};
CEAFF08925DFC6B200DF4EBF
/* CurrentWeather.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CEAFF08825DFC6B200DF4EBF
/* CurrentWeather.swift */
;
};
CEAFF08925DFC6B200DF4EBF
/* CurrentWeather.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CEAFF08825DFC6B200DF4EBF
/* CurrentWeather.swift */
;
};
...
@@ -332,6 +333,7 @@
...
@@ -332,6 +333,7 @@
CE9F01BA261B31A6009BA500
/* CoreDataError.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
CoreDataError.swift
;
sourceTree
=
"<group>"
;
};
CE9F01BA261B31A6009BA500
/* CoreDataError.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
CoreDataError.swift
;
sourceTree
=
"<group>"
;
};
CE9F01BD261B34C0009BA500
/* CoreDataAppModelConvertable.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
CoreDataAppModelConvertable.swift
;
sourceTree
=
"<group>"
;
};
CE9F01BD261B34C0009BA500
/* CoreDataAppModelConvertable.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
CoreDataAppModelConvertable.swift
;
sourceTree
=
"<group>"
;
};
CE9F01C0261B3776009BA500
/* CoreDataUtils.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
CoreDataUtils.swift
;
sourceTree
=
"<group>"
;
};
CE9F01C0261B3776009BA500
/* CoreDataUtils.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
CoreDataUtils.swift
;
sourceTree
=
"<group>"
;
};
CE9F01CB261C9A6D009BA500
/* AppData.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
AppData.swift
;
sourceTree
=
"<group>"
;
};
CEAD00A02577B2D5003596AD
/* StuffThatIsPresentInTheMainProject.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
StuffThatIsPresentInTheMainProject.swift
;
sourceTree
=
"<group>"
;
};
CEAD00A02577B2D5003596AD
/* StuffThatIsPresentInTheMainProject.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
StuffThatIsPresentInTheMainProject.swift
;
sourceTree
=
"<group>"
;
};
CEAFF08225DFC67F00DF4EBF
/* Location.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
Location.swift
;
sourceTree
=
"<group>"
;
};
CEAFF08225DFC67F00DF4EBF
/* Location.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
Location.swift
;
sourceTree
=
"<group>"
;
};
CEAFF08825DFC6B200DF4EBF
/* CurrentWeather.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
CurrentWeather.swift
;
sourceTree
=
"<group>"
;
};
CEAFF08825DFC6B200DF4EBF
/* CurrentWeather.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
CurrentWeather.swift
;
sourceTree
=
"<group>"
;
};
...
@@ -860,6 +862,7 @@
...
@@ -860,6 +862,7 @@
CE89628F26175DF400CA274A
/* Objects */
=
{
CE89628F26175DF400CA274A
/* Objects */
=
{
isa
=
PBXGroup
;
isa
=
PBXGroup
;
children
=
(
children
=
(
CE9F01CB261C9A6D009BA500
/* AppData.swift */
,
CE89629926175DF500CA274A
/* Human */
,
CE89629926175DF500CA274A
/* Human */
,
CE89629026175DF400CA274A
/* Machine */
,
CE89629026175DF400CA274A
/* Machine */
,
);
);
...
@@ -1227,6 +1230,7 @@
...
@@ -1227,6 +1230,7 @@
CD593BDC2608CDF100C93428
/* Date+Now.swift in Sources */
,
CD593BDC2608CDF100C93428
/* Date+Now.swift in Sources */
,
CD17C60225D15C8500EE884E
/* CoordinatorProtocol.swift in Sources */
,
CD17C60225D15C8500EE884E
/* CoordinatorProtocol.swift in Sources */
,
CDA5542825EF734200A2E08C
/* TodayCellFactory.swift in Sources */
,
CDA5542825EF734200A2E08C
/* TodayCellFactory.swift in Sources */
,
CE9F01CC261C9A6E009BA500
/* AppData.swift in Sources */
,
CEF959742600C3A400975FAA
/* FlurryAnalyticsService.swift in Sources */
,
CEF959742600C3A400975FAA
/* FlurryAnalyticsService.swift in Sources */
,
CE2847602615A8AD006C8DC5
/* BlendHealthSource.swift in Sources */
,
CE2847602615A8AD006C8DC5
/* BlendHealthSource.swift in Sources */
,
CD86C22225F0DCCB00F38A16
/* PrecipitationView.swift in Sources */
,
CD86C22225F0DCCB00F38A16
/* PrecipitationView.swift in Sources */
,
...
...
1Weather/Storage/CoreData/1WModel.xcdatamodeld/Model.xcdatamodel/contents
View file @
a760d66e
...
@@ -6,7 +6,7 @@
...
@@ -6,7 +6,7 @@
<relationship
name=
"health"
optional=
"YES"
maxCount=
"1"
deletionRule=
"Nullify"
destinationEntity=
"CoreHealth"
inverseName=
"airQuality"
inverseEntity=
"CoreHealth"
/>
<relationship
name=
"health"
optional=
"YES"
maxCount=
"1"
deletionRule=
"Nullify"
destinationEntity=
"CoreHealth"
inverseName=
"airQuality"
inverseEntity=
"CoreHealth"
/>
</entity>
</entity>
<entity
name=
"CoreAppData"
representedClassName=
"CoreAppData"
syncable=
"YES"
>
<entity
name=
"CoreAppData"
representedClassName=
"CoreAppData"
syncable=
"YES"
>
<attribute
name=
"selectedIndex"
optional=
"YES"
attributeType=
"
Integer 16"
defaultValueString=
"0"
usesScalarValueType=
"YES
"
/>
<attribute
name=
"selectedIndex"
optional=
"YES"
attributeType=
"
Decimal"
defaultValueString=
"0
"
/>
<relationship
name=
"locations"
toMany=
"YES"
deletionRule=
"Cascade"
ordered=
"YES"
destinationEntity=
"CoreLocation"
inverseName=
"appData"
inverseEntity=
"CoreLocation"
/>
<relationship
name=
"locations"
toMany=
"YES"
deletionRule=
"Cascade"
ordered=
"YES"
destinationEntity=
"CoreLocation"
inverseName=
"appData"
inverseEntity=
"CoreLocation"
/>
</entity>
</entity>
<entity
name=
"CoreCurrentWeather"
representedClassName=
"CoreCurrentWeather"
syncable=
"YES"
>
<entity
name=
"CoreCurrentWeather"
representedClassName=
"CoreCurrentWeather"
syncable=
"YES"
>
...
...
1Weather/Storage/CoreData/CoreDataStorage.swift
View file @
a760d66e
...
@@ -29,34 +29,63 @@ public class CoreDataStorage: Storage {
...
@@ -29,34 +29,63 @@ public class CoreDataStorage: Storage {
guard
let
context
=
self
.
managedContext
else
{
guard
let
context
=
self
.
managedContext
else
{
return
return
}
}
self
.
deleteAll
(
in
:
context
)
do
{
try
self
.
deleteAll
(
in
:
context
)
let
appData
=
AppData
(
selectedIndex
:
selectedIndex
,
locations
:
locations
)
if
let
coreAppData
=
try
CoreAppData
(
context
:
context
,
appModel
:
appData
)
{
context
.
insert
(
coreAppData
)
try
self
.
save
(
context
:
context
)
}
}
catch
{
self
.
log
.
error
(
"Error during saving:
\(
error
)
"
)
}
}
}
}
}
public
func
load
(
completion
:
StorageCompletion
)
{
public
func
load
(
completion
:
@escaping
StorageCompletion
)
{
managedContext
?
.
perform
{
managedContext
?
.
perform
{
[
weak
self
]
in
guard
let
self
=
self
else
{
return
}
guard
let
context
=
self
.
managedContext
else
{
return
}
let
completionOnMain
:
StorageCompletion
=
{
(
locations
,
selectedIndex
,
error
)
in
DispatchQueue
.
main
.
async
{
completion
(
locations
,
selectedIndex
,
error
)
}
}
do
{
let
fetchRequest
:
NSFetchRequest
<
CoreAppData
>
=
CoreAppData
.
fetchRequest
()
fetchRequest
.
fetchLimit
=
1
let
results
=
try
context
.
fetch
(
fetchRequest
)
guard
let
coreAppData
=
results
.
first
else
{
completionOnMain
([],
nil
,
nil
)
return
}
let
appData
:
AppData
=
try
coreAppData
.
toAppModel
()
completionOnMain
(
appData
.
locations
,
appData
.
selectedIndex
,
nil
)
}
catch
{
self
.
log
.
error
(
"Error during load:
\(
error
)
"
)
completionOnMain
(
nil
,
nil
,
error
)
}
}
}
}
}
private
func
deleteAll
(
in
context
:
NSManagedObjectContext
)
{
private
func
deleteAll
(
in
context
:
NSManagedObjectContext
)
throws
{
#warning("Not implemented!")
let
fetchRequest
:
NSFetchRequest
<
CoreAppData
>
=
CoreAppData
.
fetchRequest
()
//TODO: implement
let
appDataObjects
=
try
context
.
fetch
(
fetchRequest
)
if
appDataObjects
.
count
>
1
{
log
.
warning
(
"Somehow we ended up with more than 1 CoreAppData objects in the DB... deleting them all."
)
}
for
appData
in
appDataObjects
{
context
.
delete
(
appData
)
}
}
}
private
func
saveContext
()
{
private
func
save
(
context
:
NSManagedObjectContext
)
throws
{
guard
let
context
=
managedContext
else
{
log
.
warning
(
"saveContext: no context."
)
return
}
if
context
.
hasChanges
{
if
context
.
hasChanges
{
do
{
try
context
.
save
()
try
context
.
save
()
}
catch
{
let
nserror
=
error
as
NSError
log
.
error
(
"Error saving:
\(
nserror
)
,
\(
nserror
.
userInfo
)
"
)
}
}
}
}
}
}
}
1Weather/Storage/CoreData/Objects/AppData.swift
0 → 100644
View file @
a760d66e
//
// AppData.swift
// 1Weather
//
// Created by Demid Merzlyakov on 06.04.2021.
//
import
Foundation
/// A helper structure, so that we could work with CoreAppData the same way we work with everything else.
public
struct
AppData
{
public
let
selectedIndex
:
Int
?
public
let
locations
:
[
Location
]
}
1Weather/Storage/CoreData/Objects/Human/CoreAppData.swift
View file @
a760d66e
import
Foundation
import
Foundation
import
CoreData
@objc(CoreAppData)
@objc(CoreAppData)
open
class
CoreAppData
:
_CoreAppData
{
open
class
CoreAppData
:
_CoreAppData
,
CoreDataAppModelConvertable
{
typealias
AppModel
=
AppData
func
toAppModel
()
throws
->
AppData
{
var
appModelLocations
=
[
Location
]()
try
CoreDataUtils
.
foreach
(
in
:
self
.
locations
,
of
:
self
,
attributeName
:
"locations"
)
{
(
coreLocation
:
CoreLocation
)
in
appModelLocations
.
append
(
try
coreLocation
.
toAppModel
())
}
let
result
=
AppModel
(
selectedIndex
:
self
.
selectedIndex
?
.
intValue
,
locations
:
appModelLocations
)
return
result
}
/// This is here just so that we could inherit the generated init(managedObjectContext) convenience initializer.
public
override
init
(
entity
:
NSEntityDescription
,
insertInto
context
:
NSManagedObjectContext
?)
{
super
.
init
(
entity
:
entity
,
insertInto
:
context
)
}
required
public
init
?(
context
:
NSManagedObjectContext
,
appModel
:
AppData
?)
throws
{
guard
let
appModel
=
appModel
else
{
return
nil
}
self
.
init
(
managedObjectContext
:
context
)
if
let
selectedIndex
=
appModel
.
selectedIndex
{
self
.
selectedIndex
=
NSDecimalNumber
(
value
:
selectedIndex
)
}
self
.
locations
=
NSOrderedSet
(
array
:
try
appModel
.
locations
.
compactMap
{
try
CoreLocation
(
context
:
context
,
appModel
:
$0
)})
}
}
}
1Weather/Storage/CoreData/Objects/Machine/_CoreAppData.swift
View file @
a760d66e
...
@@ -43,7 +43,7 @@ open class _CoreAppData: NSManagedObject {
...
@@ -43,7 +43,7 @@ open class _CoreAppData: NSManagedObject {
// MARK: - Properties
// MARK: - Properties
@NSManaged
open
@NSManaged
open
var
selectedIndex
:
Int16
// Optional scalars not supported
var
selectedIndex
:
NSDecimalNumber
?
// MARK: - Relationships
// MARK: - Relationships
...
...
1Weather/Storage/Storage.swift
View file @
a760d66e
...
@@ -7,9 +7,9 @@
...
@@ -7,9 +7,9 @@
import
Foundation
import
Foundation
public
typealias
StorageCompletion
=
([
Location
]?,
selectedIndex
:
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
:
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