Commit 6ed5b084 by Demid Merzlyakov

Merge branch 'feature/storage'

parents f6ef091a 5c59605f
...@@ -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")!) {
...@@ -44,49 +45,67 @@ public class LocationManager { ...@@ -44,49 +45,67 @@ public class LocationManager {
public typealias CurrentLocationCompletion = (LocationRequestResult) -> () public typealias CurrentLocationCompletion = (LocationRequestResult) -> ()
public private(set) var locations = [Location]() { private var _locations = [Location]()
didSet { private var _selectedLocationIndex: Int?
private func set(locations: [Location], selectedIndex: Int?) {
DispatchQueue.main.async { [weak self] in
self?._locations = locations
self?._selectedLocationIndex = selectedIndex
self?.handleLocationsChange(locationsChanged: true, selectedLocationChanged: true)
}
}
private func handleLocationsChange(locationsChanged: Bool, selectedLocationChanged: Bool) {
if locationsChanged {
log.info("Locations list updated: \(locations.map { $0.description }.joined(separator: ", "))") log.info("Locations list updated: \(locations.map { $0.description }.joined(separator: ", "))")
let newValue = locations
if let selectedIndex = self.selectedLocationIndex, selectedIndex >= newValue.count {
self.selectedLocationIndex = newValue.count > 0 ? 0 : nil
}
else {
updateAllWeatherIfNeeded() //TODO: the whole flow is not optimal.
self.delegates.invoke { (delegate) in
delegate.locationManager(self, changedSelectedLocation: self.selectedLocation)
}
}
self.delegates.invoke { [weak self] (delegate) in self.delegates.invoke { [weak self] (delegate) in
guard let self = self else { return } guard let self = self else { return }
delegate.locationManager(self, updatedLocationsList: self.locations) delegate.locationManager(self, updatedLocationsList: self.locations)
} }
} }
if selectedLocationChanged {
let newLocation = self.selectedLocation
self.delegates.invoke { [weak self] (delegate) in
guard let self = self else { return }
delegate.locationManager(self, changedSelectedLocation: newLocation)
}
}
storage.save(locations: locations, selectedIndex: selectedLocationIndex)
updateAllWeatherIfNeeded()
} }
private var selectedLocationIndex: Int? { public private(set) var locations: [Location] {
didSet { get {
var oldLocation: Location? return _locations
if let oldValue = oldValue, oldValue < locations.count { }
oldLocation = locations[oldValue] set {
} if let selectedLocation = self.selectedLocation {
var newLocation: Location? if let newSelectedIndex = newValue.firstIndex(where: { $0 == selectedLocation }) {
if let newValue = selectedLocationIndex, newValue < locations.count { _selectedLocationIndex = newSelectedIndex
newLocation = locations[newValue] }
else {
_selectedLocationIndex = nil
}
} }
if oldLocation?.description != newLocation?.description { if _selectedLocationIndex == nil && !newValue.isEmpty {
log.info("Current location changed to: \(selectedLocation?.description ?? "nil")") _selectedLocationIndex = 0
} }
log.info("Location updated.") _locations = newValue
DispatchQueue.main.async { handleLocationsChange(locationsChanged: true, selectedLocationChanged: true)
self.delegates.invoke { [weak self] (delegate) in }
guard let self = self else { return } }
delegate.locationManager(self, changedSelectedLocation: newLocation)
} private var selectedLocationIndex: Int? {
get {
return _selectedLocationIndex
}
set {
_selectedLocationIndex = newValue
if newValue == nil && !locations.isEmpty {
_selectedLocationIndex = 0
} }
updateAllWeatherIfNeeded() handleLocationsChange(locationsChanged: false, selectedLocationChanged: true)
} }
} }
...@@ -94,7 +113,12 @@ public class LocationManager { ...@@ -94,7 +113,12 @@ public class LocationManager {
get { get {
guard let index = selectedLocationIndex else { guard let index = selectedLocationIndex else {
// TODO: don't do it this way, because we won't be able to tell that no location is currently selected! // TODO: don't do it this way, because we won't be able to tell that no location is currently selected!
return defaultLocation if locations.count > 0 {
return locations.first
}
else {
return defaultLocation
}
} }
guard index < locations.count else { guard index < locations.count else {
assertionFailure("This shouldn't happen. Got to investigate.") assertionFailure("This shouldn't happen. Got to investigate.")
...@@ -125,14 +149,30 @@ public class LocationManager { ...@@ -125,14 +149,30 @@ 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
DispatchQueue.main.async {
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.set(locations: locations, selectedIndex: selectedIndex)
}
}
} }
public func updateAllWeatherIfNeeded() { public func updateAllWeatherIfNeeded() {
...@@ -218,7 +258,7 @@ public class LocationManager { ...@@ -218,7 +258,7 @@ public class LocationManager {
DispatchQueue.main.async { DispatchQueue.main.async {
self.log.info("Update weather finished for \(location)") self.log.info("Update weather finished for \(location)")
if let indexToUpdate = self.locations.firstIndex(where: { $0 == updatedLocation }) { if let indexToUpdate = self.locations.firstIndex(where: { $0 == updatedLocation }) {
self.locations[indexToUpdate] = updatedLocation self.locations[indexToUpdate] = self.locations[indexToUpdate].mergedWith(incrementalChanges: updatedLocation)
} }
else if self.defaultLocation == updatedLocation { else if self.defaultLocation == updatedLocation {
self.defaultLocation = self.defaultLocation.mergedWith(incrementalChanges: updatedLocation) self.defaultLocation = self.defaultLocation.mergedWith(incrementalChanges: updatedLocation)
...@@ -229,7 +269,6 @@ public class LocationManager { ...@@ -229,7 +269,6 @@ public class LocationManager {
} }
} }
} }
// TODO: update weather for all locations
public func addIfNeeded(location: Location, selectLocation: Bool) { public func addIfNeeded(location: Location, selectLocation: Bool) {
// If the location is partially incomplete (e.g. coordinates are missing, or country / city / region), then some of this information will be returned by the weather update, but we may need to consider reverse geocoding here as well, if needed. // If the location is partially incomplete (e.g. coordinates are missing, or country / city / region), then some of this information will be returned by the weather update, but we may need to consider reverse geocoding here as well, if needed.
......
...@@ -65,6 +65,16 @@ public struct Location { ...@@ -65,6 +65,16 @@ public struct Location {
public var cityId: String { public var cityId: String {
return "\(self.countryCode ?? ""):\(self.region ?? ""):\(self.cityName ?? "")" return "\(self.countryCode ?? ""):\(self.region ?? ""):\(self.cityName ?? "")"
} }
public func equals(to other: Location, onlyCompareLocationInfo: Bool) -> Bool {
guard !onlyCompareLocationInfo else {
return self == other
}
guard self == other else { return false }
guard self.lastWeatherUpdateDate == other.lastWeatherUpdateDate else { return false }
guard self.health?.lastUpdateTime == other.health?.lastUpdateTime else { return false }
return true
}
} }
extension Location: Equatable, Hashable { extension Location: Equatable, Hashable {
......
//
// CoreDataAppModelConvertable.swift
// 1Weather
//
// Created by Demid Merzlyakov on 05.04.2021.
//
import Foundation
import CoreData
protocol CoreDataAppModelConvertable {
associatedtype AppModel
func toAppModel() throws -> AppModel
init?(context: NSManagedObjectContext, appModel: AppModel?) throws
}
//
// CoreDataError.swift
// 1Weather
//
// Created by Demid Merzlyakov on 05.04.2021.
//
import Foundation
struct CoreDataError {
struct SaveAttributeError<T>: Error {
let entityName: String?
let attributeName: String
let attributeValue: T
let nestedError: Error?
init(entity: Any?, attributeName: String, value: T, nestedError: Error? = nil) {
if let entity = entity {
self.entityName = String(describing: type(of: entity))
}
else {
self.entityName = nil
}
self.attributeName = attributeName
self.attributeValue = value
self.nestedError = nestedError
}
}
struct LoadAttributeError<T>: Error {
let entityName: String?
let attributeName: String
let attributeValue: T
let nestedError: Error?
init(entity: Any?, attributeName: String, value: T, nestedError: Error? = nil) {
if let entity = entity {
self.entityName = String(describing: type(of: entity))
}
else {
self.entityName = nil
}
self.attributeName = attributeName
self.attributeValue = value
self.nestedError = nestedError
}
}
}
//
// CoreDataStorage.swift
// 1Weather
//
// Created by Demid Merzlyakov on 02.04.2021.
//
import Foundation
import CoreData
public class CoreDataStorage: Storage {
private var lastSavedAppData: AppData? = nil
private let log = Logger(componentName: "CoreDataStorage 💾")
private lazy var managedContext: NSManagedObjectContext? = {
persistentContainer.newBackgroundContext()
}()
private lazy var persistentContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: "1WModel")
container.loadPersistentStores { [weak self] (description, error) in
if let error = error {
self?.log.error("Error loading persistent stores: \(error)")
}
}
return container
}()
public func save(locations: [Location], selectedIndex: Int?) {
log.info("Save: start")
managedContext?.perform { [weak self] in
guard let self = self else { return }
let appData = AppData(selectedIndex: selectedIndex, locations: locations)
guard appData != self.lastSavedAppData else {
self.log.info("Save: no changes, skip")
return
}
guard let context = self.managedContext else {
return
}
do {
try self.deleteAll(in: context)
if let coreAppData = try CoreAppData(context: context, appModel: appData) {
context.insert(coreAppData)
try self.save(context: context)
self.lastSavedAppData = appData
}
self.log.info("Save: success")
}
catch {
self.log.error("Save: error: \(error)")
}
}
}
public func load(completion: @escaping StorageCompletion) {
log.info("Load: start")
managedContext?.perform { [weak self] in
guard let self = self else { return }
guard let context = self.managedContext else {
return
}
let completionWithErrorHandling: 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))")
}
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 {
completionWithErrorHandling([], nil, nil)
return
}
let appData: AppData = try coreAppData.toAppModel()
self.lastSavedAppData = appData
completionWithErrorHandling(appData.locations, appData.selectedIndex, nil)
}
catch {
self.log.error("Error during load: \(error)")
completionWithErrorHandling(nil, nil, error)
}
}
}
private func deleteAll(in context: NSManagedObjectContext) throws {
log.debug("Delete: start")
let fetchRequest: NSFetchRequest<CoreAppData> = CoreAppData.fetchRequest()
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.")
}
if appDataObjects.count > 0 {
log.debug("Delete: \(appDataObjects.count) objects...")
}
for appData in appDataObjects {
context.delete(appData)
}
log.info("Delete: success")
}
private func save(context: NSManagedObjectContext) throws {
log.info("Context save: start")
if context.hasChanges {
try context.save()
log.info("Context save: success")
}
else {
log.info("Context save: no need")
}
}
}
//
// CoreDataUtils.swift
// 1Weather
//
// Created by Demid Merzlyakov on 05.04.2021.
//
import Foundation
import CoreData
struct CoreDataUtils {
public static func foreach<T>(in set: NSOrderedSet, of entity: Any, attributeName: String, do action: (T) throws -> ()) throws {
for elem in set {
guard let converted = elem as? T else {
throw CoreDataError.LoadAttributeError(entity: entity, attributeName: attributeName, value: set)
}
try action(converted)
}
}
public static func measurementToData<T>(_ measurement: Measurement<T>?, in entity: Any, attributeName: String) throws -> Data? {
guard let measurement = measurement else {
return nil
}
let encoder = JSONEncoder()
do {
let result = try encoder.encode(measurement)
return result
}
catch {
throw CoreDataError.SaveAttributeError(entity: entity, attributeName: attributeName, value: measurement, nestedError: error)
}
}
public static func measurement<T>(from data: Data?, in entity: Any, attributeName: String) throws -> Measurement<T>? {
guard let data = data else {
return nil
}
let decoder = JSONDecoder()
do {
let result = try decoder.decode(Measurement<T>.self, from: data)
return result
}
catch {
let valueStr = String(data: data, encoding: .utf8) ?? "<couldn't-turn-into-string>"
throw CoreDataError.LoadAttributeError(entity: entity, attributeName: attributeName, value: valueStr, nestedError: error)
}
}
public static func timeZone(from timeZoneString: String, in entity: Any, attributeName: String) throws -> TimeZone {
guard let timeZone = TimeZone(abbreviation: timeZoneString) else {
throw CoreDataError.LoadAttributeError(entity: entity, attributeName: attributeName, value: timeZoneString)
}
return timeZone
}
public static func timeZoneToString(_ timeZone: TimeZone, in entity: Any, attributeName: String) throws -> String {
guard let result = timeZone.abbreviation() else {
throw CoreDataError.SaveAttributeError(entity: entity, attributeName: attributeName, value: timeZone)
}
return result
}
public static func appValue<T>(name: String, value: T.RawValue, in entity: Any) throws -> T where T: RawRepresentable {
guard let result = T(rawValue: value) else {
throw CoreDataError.LoadAttributeError(entity: entity, attributeName: name, value: value)
}
return result
}
// 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 {
return nil
}
return try appValue(name: name, value: value, in: entity)
}
}
//
// 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: Equatable {
public let selectedIndex: Int?
public let locations: [Location]
public static func == (lhs: Self, rhs: Self) -> Bool {
guard lhs.selectedIndex == rhs.selectedIndex else { return false }
guard lhs.locations.count == rhs.locations.count else { return false }
for (i, location) in lhs.locations.enumerated() {
let otherLocation = rhs.locations[i]
guard location.equals(to: otherLocation, onlyCompareLocationInfo: false) else {
return false
}
}
return true
}
}
import Foundation
import CoreData
@objc(CoreAirQuality)
open class CoreAirQuality: _CoreAirQuality, CoreDataAppModelConvertable {
func toAppModel() throws -> AirQuality {
let result = AirQuality(index: self.index, advice: self.advice)
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: AirQuality?) throws {
guard let appModel = appModel else {
return nil
}
self.init(managedObjectContext: context)
self.index = appModel.index
self.advice = appModel.advice
}
typealias AppModel = AirQuality
}
import Foundation
import CoreData
@objc(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)})
}
}
import Foundation
import CoreData
@objc(CoreCurrentWeather)
open class CoreCurrentWeather: _CoreCurrentWeather, CoreDataAppModelConvertable {
typealias AppModel = CurrentWeather
func toAppModel() throws -> CurrentWeather {
let timeZone = try CoreDataUtils.timeZone(from: self.timeZone, in: self, attributeName: "timeZone")
let weekDay: WeekDay = try CoreDataUtils.appValue(name: "weekDay", value: self.weekDay, in: self)
var result = CurrentWeather(lastTimeUpdated: self.lastTimeUpdated, date: self.date, timeZone: timeZone, weekDay: weekDay, isDay: self.isDay)
result.type = try CoreDataUtils.appValue(name: "type", value: self.type, in: self)
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.windSpeed = try CoreDataUtils.measurement(from: self.windSpeed, in: self, attributeName: "windSpeed")
result.windDirection = try CoreDataUtils.appValueOptional(name: "windDirection", value: self.windDirection, in: self)
if let precipProb = self.precipitationProbability {
result.precipitationProbability = Percent(precipProb.uintValue)
}
result.temp = try CoreDataUtils.measurement(from: self.temp, in: self, attributeName: "temp")
result.apparentTemp = try CoreDataUtils.measurement(from: self.apparentTemp, in: self, attributeName: "apparentTemp")
if let humidity = self.humidity {
result.humidity = Percent(humidity.uintValue)
}
result.visibility = try CoreDataUtils.measurement(from: self.visibility, in: self, attributeName: "visibility")
result.pressure = try CoreDataUtils.measurement(from: self.pressure, in: self, attributeName: "pressure")
result.sunrise = self.sunrise
result.sunset = self.sunset
result.sunState = try CoreDataUtils.appValueOptional(name: "sunState", value: self.sunState, in: self)
result.moonrise = self.moonrise
result.moonset = self.moonset
result.approximateMoonrise = self.approximateMoonrise
result.moonState = try CoreDataUtils.appValueOptional(name: "moonState", value: self.moonState, in: self)
result.moonPhase = try CoreDataUtils.appValueOptional(name: "moonPhase", value: self.moonPhase, in: self)
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: CurrentWeather?) throws {
guard let appModel = appModel else {
return nil
}
self.init(managedObjectContext: context)
self.lastTimeUpdated = appModel.lastTimeUpdated
self.date = appModel.date
self.timeZone = try CoreDataUtils.timeZoneToString(appModel.timeZone, in: self, attributeName: "timeZone")
self.weekDay = appModel.weekDay.rawValue
self.type = appModel.type.rawValue
self.isDay = appModel.isDay
self.minTemp = try CoreDataUtils.measurementToData(appModel.minTemp, in: self, attributeName: "minTemp")
self.maxTemp = try CoreDataUtils.measurementToData(appModel.maxTemp, in: self, attributeName: "maxTemp")
self.windSpeed = try CoreDataUtils.measurementToData(appModel.windSpeed, in: self, attributeName: "windSpeed")
self.windDirection = appModel.windDirection?.rawValue
if let precipProb = appModel.precipitationProbability {
self.precipitationProbability = NSDecimalNumber(value: precipProb)
}
self.temp = try CoreDataUtils.measurementToData(appModel.temp, in: self, attributeName: "temp")
self.apparentTemp = try CoreDataUtils.measurementToData(appModel.apparentTemp, in: self, attributeName: "apparentTemp")
if let humidity = appModel.humidity {
self.humidity = NSDecimalNumber(value: humidity)
}
self.visibility = try CoreDataUtils.measurementToData(appModel.visibility, in: self, attributeName: "visibility")
self.pressure = try CoreDataUtils.measurementToData(appModel.pressure, in: self, attributeName: "pressure")
self.sunrise = appModel.sunrise
self.sunset = appModel.sunset
self.sunState = appModel.sunState?.rawValue
self.moonrise = appModel.moonrise
self.moonset = appModel.moonset
self.approximateMoonrise = appModel.approximateMoonrise
self.moonState = appModel.moonState?.rawValue
self.moonPhase = appModel.moonPhase?.rawValue
}
}
import Foundation
import CoreData
@objc(CoreDailyWeather)
open class CoreDailyWeather: _CoreDailyWeather, CoreDataAppModelConvertable {
typealias AppModel = DailyWeather
func toAppModel() throws -> DailyWeather {
let timeZone = try CoreDataUtils.timeZone(from: self.timeZone, in: self, attributeName: "timeZone")
let weekDay: WeekDay = try CoreDataUtils.appValue(name: "weekDay", value: self.weekDay, in: self)
var result = DailyWeather(lastTimeUpdated: lastTimeUpdated, date: date, timeZone: timeZone, weekDay: weekDay)
result.type = try CoreDataUtils.appValue(name: "type", value: self.type, in: self)
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.windSpeed = try CoreDataUtils.measurement(from: self.windSpeed, in: self, attributeName: "windSpeed")
result.windDirection = try CoreDataUtils.appValueOptional(name: "windDirection", value: self.windDirection, in: self)
if let precipProb = self.precipitationProbability {
result.precipitationProbability = Percent(precipProb.uintValue)
}
result.sunrise = self.sunrise
result.sunset = self.sunset
result.sunState = try CoreDataUtils.appValueOptional(name: "sunState", value: self.sunState, in: self)
result.moonrise = self.moonrise
result.moonset = self.moonset
result.moonState = try CoreDataUtils.appValueOptional(name: "moonState", value: self.moonState, in: self)
result.moonPhase = try CoreDataUtils.appValueOptional(name: "moonPhase", value: self.moonPhase, in: self)
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: DailyWeather?) throws {
guard let appModel = appModel else {
return nil
}
self.init(managedObjectContext: context)
self.date = appModel.date
self.lastTimeUpdated = appModel.lastTimeUpdated
self.minTemp = try CoreDataUtils.measurementToData(appModel.minTemp, in: self, attributeName: "minTemp")
self.maxTemp = try CoreDataUtils.measurementToData(appModel.maxTemp, in: self, attributeName: "maxTemp")
self.moonPhase = appModel.moonPhase?.rawValue
self.moonrise = appModel.moonrise
self.moonset = appModel.moonset
self.moonState = appModel.moonState?.rawValue
if let precipProb = appModel.precipitationProbability {
self.precipitationProbability = NSDecimalNumber(value: precipProb)
}
self.sunrise = appModel.sunrise
self.sunset = appModel.sunset
self.sunState = appModel.sunState?.rawValue
self.timeZone = try CoreDataUtils.timeZoneToString(appModel.timeZone, in: self, attributeName: "timeZone")
self.type = appModel.type.rawValue
self.weekDay = appModel.weekDay.rawValue
self.windDirection = appModel.windDirection?.rawValue
self.windSpeed = try CoreDataUtils.measurementToData(appModel.windSpeed, in: self, attributeName: "windSpeed")
}
}
import Foundation
import CoreData
@objc(CoreHealth)
open class CoreHealth: _CoreHealth, CoreDataAppModelConvertable {
func toAppModel() throws -> Health {
let airQuality = try self.airQuality?.toAppModel()
var pollutants = [String: Pollutant]()
try CoreDataUtils.foreach(in: self.pollutants, of: self, attributeName: "pollutants") { (corePollutant: CorePollutant) in
let pollutant = try corePollutant.toAppModel()
pollutants[pollutant.name] = pollutant
}
let result = Health(lastUpdateTime: self.lastUpdateTime, airQuality: airQuality, pollutants: pollutants)
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: Health?) throws {
guard let appModel = appModel else {
return nil
}
self.init(managedObjectContext: context)
self.lastUpdateTime = appModel.lastUpdateTime
self.airQuality = try CoreAirQuality(context: context, appModel: appModel.airQuality)
self.pollutants = NSOrderedSet(array: try appModel.pollutants.compactMap { try CorePollutant(context: context, appModel: $0.value) })
}
typealias AppModel = Health
}
import Foundation
import CoreData
@objc(CoreHourlyWeather)
open class CoreHourlyWeather: _CoreHourlyWeather, CoreDataAppModelConvertable {
func toAppModel() throws -> HourlyWeather {
let timeZone = try CoreDataUtils.timeZone(from: self.timeZone, in: self, attributeName: "timeZone")
let weekDay: WeekDay = try CoreDataUtils.appValue(name: "weekDay", value: self.weekDay, in: self)
var result = HourlyWeather(lastTimeUpdated: self.lastTimeUpdated, date: self.date, timeZone: timeZone, weekDay: weekDay, isDay: self.isDay)
result.type = try CoreDataUtils.appValue(name: "type", value: self.type, in: self)
result.isDay = self.isDay
result.temp = try CoreDataUtils.measurement(from: self.temp, in: self, attributeName: "temp")
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.windDirection = try CoreDataUtils.appValueOptional(name: "windDirection", value: self.windDirection, in: self)
if let precipProb = self.precipitationProbability {
result.precipitationProbability = Percent(precipProb.uintValue)
}
if let humidity = self.humidity {
result.humidity = Percent(humidity.uintValue)
}
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: HourlyWeather?) throws {
guard let appModel = appModel else {
return nil
}
self.init(managedObjectContext: context)
self.lastTimeUpdated = appModel.lastTimeUpdated
self.date = appModel.date
self.timeZone = try CoreDataUtils.timeZoneToString(appModel.timeZone, in: self, attributeName: "timeZone")
self.weekDay = appModel.weekDay.rawValue
self.type = appModel.type.rawValue
self.isDay = appModel.isDay
self.temp = try CoreDataUtils.measurementToData(appModel.temp, in: self, attributeName: "temp")
self.apparentTemp = try CoreDataUtils.measurementToData(appModel.apparentTemp, in: self, attributeName: "apparentTemp")
self.windSpeed = try CoreDataUtils.measurementToData(appModel.windSpeed, in: self, attributeName: "windSpeed")
self.windDirection = appModel.windDirection?.rawValue
if let precipProb = appModel.precipitationProbability {
self.precipitationProbability = NSDecimalNumber(value: precipProb)
}
if let humidity = appModel.humidity {
self.humidity = NSDecimalNumber(value: humidity)
}
}
typealias AppModel = HourlyWeather
}
import Foundation
import CoreData
@objc(CoreLocation)
open class CoreLocation: _CoreLocation, CoreDataAppModelConvertable {
typealias AppModel = Location
func toAppModel() throws -> Location {
let timeZone = try CoreDataUtils.timeZone(from: self.timeZone, in: self, attributeName: "timeZone")
var location = Location(deviceLocation: self.deviceLocation, timeZone: timeZone)
location.lastWeatherUpdateDate = self.lastWeatherUpdateDate
if let lat = self.latitude?.doubleValue, let lon = self.longitude?.doubleValue {
location.coordinates = CLLocationCoordinate2D(latitude: lat, longitude: lon)
}
location.imageName = self.imageName
location.countryCode = self.countryCode
location.countryName = self.countryName
location.region = self.region
location.cityName = self.cityName
location.nickname = self.nickname
location.zip = self.zip
location.fipsCode = self.fipsCode
location.today = try (self.today?.toAppModel())
try CoreDataUtils.foreach(in: self.daily, of: self, attributeName: "daily") { (coreDaily: CoreDailyWeather) in
location.daily.append(try coreDaily.toAppModel())
}
try CoreDataUtils.foreach(in: self.hourly, of: self, attributeName: "hourly") { (coreHourly: CoreHourlyWeather) in
location.hourly.append(try coreHourly.toAppModel())
}
location.health = try self.health?.toAppModel()
return location
}
/// 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: Location?) throws {
guard let appModel = appModel else {
return nil
}
self.init(managedObjectContext: context)
self.deviceLocation = appModel.deviceLocation
self.lastWeatherUpdateDate = appModel.lastWeatherUpdateDate
if let coordinates = appModel.coordinates {
self.latitude = NSDecimalNumber(value: coordinates.latitude)
self.longitude = NSDecimalNumber(value: coordinates.longitude)
}
self.imageName = appModel.imageName
self.countryCode = appModel.countryCode
self.countryName = appModel.countryName
self.region = appModel.region
self.cityName = appModel.cityName
self.nickname = appModel.nickname
self.zip = appModel.zip
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.daily = NSOrderedSet(array: appModel.daily.compactMap {elem in
skipIfError(attribute: "daily") {
try CoreDailyWeather(context: context, appModel: elem)
}
})
self.hourly = NSOrderedSet(array: appModel.hourly.compactMap {elem in
skipIfError(attribute: "hourly") {
try CoreHourlyWeather(context: context, appModel: elem)
}
})
self.health = skipIfError(attribute: "health", action: { try CoreHealth(context: context, appModel: appModel.health) })
}
private func skipIfError<T>(attribute: String, action: () throws -> T?) -> T? {
do {
let result = try action()
return result
}
catch {
Logger(componentName: "CoreLocation").error("Couldn't parse \(attribute) in CoreLocation due to error: \(error)")
return nil
}
}
}
import Foundation
import CoreData
@objc(CorePollutant)
open class CorePollutant: _CorePollutant, CoreDataAppModelConvertable {
func toAppModel() throws -> Pollutant {
let result = Pollutant(name: self.name, value: self.value)
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: Pollutant?) throws {
guard let appModel = appModel else {
return nil
}
self.init(managedObjectContext: context)
self.name = appModel.name
self.value = appModel.value
}
typealias AppModel = Pollutant
}
// DO NOT EDIT. This file is machine-generated and constantly overwritten.
// Make changes to CoreAirQuality.swift instead.
import Foundation
import CoreData
public enum CoreAirQualityAttributes: String {
case advice = "advice"
case index = "index"
}
public enum CoreAirQualityRelationships: String {
case health = "health"
}
open class _CoreAirQuality: NSManagedObject {
// MARK: - Class methods
open class func entityName () -> String {
return "CoreAirQuality"
}
open class func entity(managedObjectContext: NSManagedObjectContext) -> NSEntityDescription? {
return NSEntityDescription.entity(forEntityName: self.entityName(), in: managedObjectContext)
}
@nonobjc
open class func fetchRequest() -> NSFetchRequest<CoreAirQuality> {
return NSFetchRequest(entityName: self.entityName())
}
// MARK: - Life cycle methods
public override init(entity: NSEntityDescription, insertInto context: NSManagedObjectContext?) {
super.init(entity: entity, insertInto: context)
}
public convenience init?(managedObjectContext: NSManagedObjectContext) {
guard let entity = _CoreAirQuality.entity(managedObjectContext: managedObjectContext) else { return nil }
self.init(entity: entity, insertInto: managedObjectContext)
}
// MARK: - Properties
@NSManaged open
var advice: String!
@NSManaged open
var index: Double
// MARK: - Relationships
@NSManaged open
var health: CoreHealth?
}
// DO NOT EDIT. This file is machine-generated and constantly overwritten.
// Make changes to CoreAppData.swift instead.
import Foundation
import CoreData
public enum CoreAppDataAttributes: String {
case selectedIndex = "selectedIndex"
}
public enum CoreAppDataRelationships: String {
case locations = "locations"
}
open class _CoreAppData: NSManagedObject {
// MARK: - Class methods
open class func entityName () -> String {
return "CoreAppData"
}
open class func entity(managedObjectContext: NSManagedObjectContext) -> NSEntityDescription? {
return NSEntityDescription.entity(forEntityName: self.entityName(), in: managedObjectContext)
}
@nonobjc
open class func fetchRequest() -> NSFetchRequest<CoreAppData> {
return NSFetchRequest(entityName: self.entityName())
}
// MARK: - Life cycle methods
public override init(entity: NSEntityDescription, insertInto context: NSManagedObjectContext?) {
super.init(entity: entity, insertInto: context)
}
public convenience init?(managedObjectContext: NSManagedObjectContext) {
guard let entity = _CoreAppData.entity(managedObjectContext: managedObjectContext) else { return nil }
self.init(entity: entity, insertInto: managedObjectContext)
}
// MARK: - Properties
@NSManaged open
var selectedIndex: NSDecimalNumber?
// MARK: - Relationships
@NSManaged open
var locations: NSOrderedSet
open func locationsSet() -> NSMutableOrderedSet {
return self.locations.mutableCopy() as! NSMutableOrderedSet
}
}
extension _CoreAppData {
open func addLocations(_ objects: NSOrderedSet) {
let mutable = self.locations.mutableCopy() as! NSMutableOrderedSet
mutable.union(objects)
self.locations = mutable.copy() as! NSOrderedSet
}
open func removeLocations(_ objects: NSOrderedSet) {
let mutable = self.locations.mutableCopy() as! NSMutableOrderedSet
mutable.minus(objects)
self.locations = mutable.copy() as! NSOrderedSet
}
open func addLocationsObject(_ value: CoreLocation) {
let mutable = self.locations.mutableCopy() as! NSMutableOrderedSet
mutable.add(value)
self.locations = mutable.copy() as! NSOrderedSet
}
open func removeLocationsObject(_ value: CoreLocation) {
let mutable = self.locations.mutableCopy() as! NSMutableOrderedSet
mutable.remove(value)
self.locations = mutable.copy() as! NSOrderedSet
}
}
// DO NOT EDIT. This file is machine-generated and constantly overwritten.
// Make changes to CoreCurrentWeather.swift instead.
import Foundation
import CoreData
public enum CoreCurrentWeatherAttributes: String {
case apparentTemp = "apparentTemp"
case approximateMoonrise = "approximateMoonrise"
case date = "date"
case humidity = "humidity"
case isDay = "isDay"
case lastTimeUpdated = "lastTimeUpdated"
case maxTemp = "maxTemp"
case minTemp = "minTemp"
case moonPhase = "moonPhase"
case moonState = "moonState"
case moonrise = "moonrise"
case moonset = "moonset"
case precipitationProbability = "precipitationProbability"
case pressure = "pressure"
case sunState = "sunState"
case sunrise = "sunrise"
case sunset = "sunset"
case temp = "temp"
case timeZone = "timeZone"
case type = "type"
case visibility = "visibility"
case weekDay = "weekDay"
case windDirection = "windDirection"
case windSpeed = "windSpeed"
}
public enum CoreCurrentWeatherRelationships: String {
case location = "location"
}
open class _CoreCurrentWeather: NSManagedObject {
// MARK: - Class methods
open class func entityName () -> String {
return "CoreCurrentWeather"
}
open class func entity(managedObjectContext: NSManagedObjectContext) -> NSEntityDescription? {
return NSEntityDescription.entity(forEntityName: self.entityName(), in: managedObjectContext)
}
@nonobjc
open class func fetchRequest() -> NSFetchRequest<CoreCurrentWeather> {
return NSFetchRequest(entityName: self.entityName())
}
// MARK: - Life cycle methods
public override init(entity: NSEntityDescription, insertInto context: NSManagedObjectContext?) {
super.init(entity: entity, insertInto: context)
}
public convenience init?(managedObjectContext: NSManagedObjectContext) {
guard let entity = _CoreCurrentWeather.entity(managedObjectContext: managedObjectContext) else { return nil }
self.init(entity: entity, insertInto: managedObjectContext)
}
// MARK: - Properties
@NSManaged open
var apparentTemp: Data?
@NSManaged open
var approximateMoonrise: Date?
@NSManaged open
var date: Date!
@NSManaged open
var humidity: NSDecimalNumber?
@NSManaged open
var isDay: Bool
@NSManaged open
var lastTimeUpdated: Date!
@NSManaged open
var maxTemp: Data?
@NSManaged open
var minTemp: Data?
@NSManaged open
var moonPhase: String?
@NSManaged open
var moonState: String?
@NSManaged open
var moonrise: Date?
@NSManaged open
var moonset: Date?
@NSManaged open
var precipitationProbability: NSDecimalNumber?
@NSManaged open
var pressure: Data?
@NSManaged open
var sunState: String?
@NSManaged open
var sunrise: Date?
@NSManaged open
var sunset: Date?
@NSManaged open
var temp: Data?
@NSManaged open
var timeZone: String!
@NSManaged open
var type: String!
@NSManaged open
var visibility: Data?
@NSManaged open
var weekDay: String!
@NSManaged open
var windDirection: String?
@NSManaged open
var windSpeed: Data?
// MARK: - Relationships
@NSManaged open
var location: CoreLocation?
}
// DO NOT EDIT. This file is machine-generated and constantly overwritten.
// Make changes to CoreDailyWeather.swift instead.
import Foundation
import CoreData
public enum CoreDailyWeatherAttributes: String {
case date = "date"
case lastTimeUpdated = "lastTimeUpdated"
case maxTemp = "maxTemp"
case minTemp = "minTemp"
case moonPhase = "moonPhase"
case moonState = "moonState"
case moonrise = "moonrise"
case moonset = "moonset"
case precipitationProbability = "precipitationProbability"
case sunState = "sunState"
case sunrise = "sunrise"
case sunset = "sunset"
case timeZone = "timeZone"
case type = "type"
case weekDay = "weekDay"
case windDirection = "windDirection"
case windSpeed = "windSpeed"
}
public enum CoreDailyWeatherRelationships: String {
case location = "location"
}
open class _CoreDailyWeather: NSManagedObject {
// MARK: - Class methods
open class func entityName () -> String {
return "CoreDailyWeather"
}
open class func entity(managedObjectContext: NSManagedObjectContext) -> NSEntityDescription? {
return NSEntityDescription.entity(forEntityName: self.entityName(), in: managedObjectContext)
}
@nonobjc
open class func fetchRequest() -> NSFetchRequest<CoreDailyWeather> {
return NSFetchRequest(entityName: self.entityName())
}
// MARK: - Life cycle methods
public override init(entity: NSEntityDescription, insertInto context: NSManagedObjectContext?) {
super.init(entity: entity, insertInto: context)
}
public convenience init?(managedObjectContext: NSManagedObjectContext) {
guard let entity = _CoreDailyWeather.entity(managedObjectContext: managedObjectContext) else { return nil }
self.init(entity: entity, insertInto: managedObjectContext)
}
// MARK: - Properties
@NSManaged open
var date: Date!
@NSManaged open
var lastTimeUpdated: Date!
@NSManaged open
var maxTemp: Data?
@NSManaged open
var minTemp: Data?
@NSManaged open
var moonPhase: String?
@NSManaged open
var moonState: String?
@NSManaged open
var moonrise: Date?
@NSManaged open
var moonset: Date?
@NSManaged open
var precipitationProbability: NSDecimalNumber?
@NSManaged open
var sunState: String?
@NSManaged open
var sunrise: Date?
@NSManaged open
var sunset: Date?
@NSManaged open
var timeZone: String!
@NSManaged open
var type: String!
@NSManaged open
var weekDay: String!
@NSManaged open
var windDirection: String?
@NSManaged open
var windSpeed: Data?
// MARK: - Relationships
@NSManaged open
var location: CoreLocation?
}
// DO NOT EDIT. This file is machine-generated and constantly overwritten.
// Make changes to CoreHealth.swift instead.
import Foundation
import CoreData
public enum CoreHealthAttributes: String {
case lastUpdateTime = "lastUpdateTime"
}
public enum CoreHealthRelationships: String {
case airQuality = "airQuality"
case location = "location"
case pollutants = "pollutants"
}
open class _CoreHealth: NSManagedObject {
// MARK: - Class methods
open class func entityName () -> String {
return "CoreHealth"
}
open class func entity(managedObjectContext: NSManagedObjectContext) -> NSEntityDescription? {
return NSEntityDescription.entity(forEntityName: self.entityName(), in: managedObjectContext)
}
@nonobjc
open class func fetchRequest() -> NSFetchRequest<CoreHealth> {
return NSFetchRequest(entityName: self.entityName())
}
// MARK: - Life cycle methods
public override init(entity: NSEntityDescription, insertInto context: NSManagedObjectContext?) {
super.init(entity: entity, insertInto: context)
}
public convenience init?(managedObjectContext: NSManagedObjectContext) {
guard let entity = _CoreHealth.entity(managedObjectContext: managedObjectContext) else { return nil }
self.init(entity: entity, insertInto: managedObjectContext)
}
// MARK: - Properties
@NSManaged open
var lastUpdateTime: Date!
// MARK: - Relationships
@NSManaged open
var airQuality: CoreAirQuality?
@NSManaged open
var location: CoreLocation?
@NSManaged open
var pollutants: NSOrderedSet
open func pollutantsSet() -> NSMutableOrderedSet {
return self.pollutants.mutableCopy() as! NSMutableOrderedSet
}
}
extension _CoreHealth {
open func addPollutants(_ objects: NSOrderedSet) {
let mutable = self.pollutants.mutableCopy() as! NSMutableOrderedSet
mutable.union(objects)
self.pollutants = mutable.copy() as! NSOrderedSet
}
open func removePollutants(_ objects: NSOrderedSet) {
let mutable = self.pollutants.mutableCopy() as! NSMutableOrderedSet
mutable.minus(objects)
self.pollutants = mutable.copy() as! NSOrderedSet
}
open func addPollutantsObject(_ value: CorePollutant) {
let mutable = self.pollutants.mutableCopy() as! NSMutableOrderedSet
mutable.add(value)
self.pollutants = mutable.copy() as! NSOrderedSet
}
open func removePollutantsObject(_ value: CorePollutant) {
let mutable = self.pollutants.mutableCopy() as! NSMutableOrderedSet
mutable.remove(value)
self.pollutants = mutable.copy() as! NSOrderedSet
}
}
// DO NOT EDIT. This file is machine-generated and constantly overwritten.
// Make changes to CoreHourlyWeather.swift instead.
import Foundation
import CoreData
public enum CoreHourlyWeatherAttributes: String {
case apparentTemp = "apparentTemp"
case date = "date"
case humidity = "humidity"
case isDay = "isDay"
case lastTimeUpdated = "lastTimeUpdated"
case precipitationProbability = "precipitationProbability"
case temp = "temp"
case timeZone = "timeZone"
case type = "type"
case weekDay = "weekDay"
case windDirection = "windDirection"
case windSpeed = "windSpeed"
}
public enum CoreHourlyWeatherRelationships: String {
case location = "location"
}
open class _CoreHourlyWeather: NSManagedObject {
// MARK: - Class methods
open class func entityName () -> String {
return "CoreHourlyWeather"
}
open class func entity(managedObjectContext: NSManagedObjectContext) -> NSEntityDescription? {
return NSEntityDescription.entity(forEntityName: self.entityName(), in: managedObjectContext)
}
@nonobjc
open class func fetchRequest() -> NSFetchRequest<CoreHourlyWeather> {
return NSFetchRequest(entityName: self.entityName())
}
// MARK: - Life cycle methods
public override init(entity: NSEntityDescription, insertInto context: NSManagedObjectContext?) {
super.init(entity: entity, insertInto: context)
}
public convenience init?(managedObjectContext: NSManagedObjectContext) {
guard let entity = _CoreHourlyWeather.entity(managedObjectContext: managedObjectContext) else { return nil }
self.init(entity: entity, insertInto: managedObjectContext)
}
// MARK: - Properties
@NSManaged open
var apparentTemp: Data?
@NSManaged open
var date: Date!
@NSManaged open
var humidity: NSDecimalNumber?
@NSManaged open
var isDay: Bool
@NSManaged open
var lastTimeUpdated: Date!
@NSManaged open
var precipitationProbability: NSDecimalNumber?
@NSManaged open
var temp: Data?
@NSManaged open
var timeZone: String!
@NSManaged open
var type: String!
@NSManaged open
var weekDay: String!
@NSManaged open
var windDirection: String?
@NSManaged open
var windSpeed: Data?
// MARK: - Relationships
@NSManaged open
var location: CoreLocation?
}
// DO NOT EDIT. This file is machine-generated and constantly overwritten.
// Make changes to CoreLocation.swift instead.
import Foundation
import CoreData
public enum CoreLocationAttributes: String {
case cityName = "cityName"
case countryCode = "countryCode"
case countryName = "countryName"
case deviceLocation = "deviceLocation"
case fipsCode = "fipsCode"
case imageName = "imageName"
case lastWeatherUpdateDate = "lastWeatherUpdateDate"
case latitude = "latitude"
case longitude = "longitude"
case nickname = "nickname"
case region = "region"
case timeZone = "timeZone"
case zip = "zip"
}
public enum CoreLocationRelationships: String {
case appData = "appData"
case daily = "daily"
case health = "health"
case hourly = "hourly"
case today = "today"
}
open class _CoreLocation: NSManagedObject {
// MARK: - Class methods
open class func entityName () -> String {
return "CoreLocation"
}
open class func entity(managedObjectContext: NSManagedObjectContext) -> NSEntityDescription? {
return NSEntityDescription.entity(forEntityName: self.entityName(), in: managedObjectContext)
}
@nonobjc
open class func fetchRequest() -> NSFetchRequest<CoreLocation> {
return NSFetchRequest(entityName: self.entityName())
}
// MARK: - Life cycle methods
public override init(entity: NSEntityDescription, insertInto context: NSManagedObjectContext?) {
super.init(entity: entity, insertInto: context)
}
public convenience init?(managedObjectContext: NSManagedObjectContext) {
guard let entity = _CoreLocation.entity(managedObjectContext: managedObjectContext) else { return nil }
self.init(entity: entity, insertInto: managedObjectContext)
}
// MARK: - Properties
@NSManaged open
var cityName: String?
@NSManaged open
var countryCode: String?
@NSManaged open
var countryName: String?
@NSManaged open
var deviceLocation: Bool
@NSManaged open
var fipsCode: String?
@NSManaged open
var imageName: String?
@NSManaged open
var lastWeatherUpdateDate: Date?
@NSManaged open
var latitude: NSDecimalNumber?
@NSManaged open
var longitude: NSDecimalNumber?
@NSManaged open
var nickname: String?
@NSManaged open
var region: String?
@NSManaged open
var timeZone: String!
@NSManaged open
var zip: String?
// MARK: - Relationships
@NSManaged open
var appData: CoreAppData
@NSManaged open
var daily: NSOrderedSet
open func dailySet() -> NSMutableOrderedSet {
return self.daily.mutableCopy() as! NSMutableOrderedSet
}
@NSManaged open
var health: CoreHealth?
@NSManaged open
var hourly: NSOrderedSet
open func hourlySet() -> NSMutableOrderedSet {
return self.hourly.mutableCopy() as! NSMutableOrderedSet
}
@NSManaged open
var today: CoreCurrentWeather?
}
extension _CoreLocation {
open func addDaily(_ objects: NSOrderedSet) {
let mutable = self.daily.mutableCopy() as! NSMutableOrderedSet
mutable.union(objects)
self.daily = mutable.copy() as! NSOrderedSet
}
open func removeDaily(_ objects: NSOrderedSet) {
let mutable = self.daily.mutableCopy() as! NSMutableOrderedSet
mutable.minus(objects)
self.daily = mutable.copy() as! NSOrderedSet
}
open func addDailyObject(_ value: CoreDailyWeather) {
let mutable = self.daily.mutableCopy() as! NSMutableOrderedSet
mutable.add(value)
self.daily = mutable.copy() as! NSOrderedSet
}
open func removeDailyObject(_ value: CoreDailyWeather) {
let mutable = self.daily.mutableCopy() as! NSMutableOrderedSet
mutable.remove(value)
self.daily = mutable.copy() as! NSOrderedSet
}
}
extension _CoreLocation {
open func addHourly(_ objects: NSOrderedSet) {
let mutable = self.hourly.mutableCopy() as! NSMutableOrderedSet
mutable.union(objects)
self.hourly = mutable.copy() as! NSOrderedSet
}
open func removeHourly(_ objects: NSOrderedSet) {
let mutable = self.hourly.mutableCopy() as! NSMutableOrderedSet
mutable.minus(objects)
self.hourly = mutable.copy() as! NSOrderedSet
}
open func addHourlyObject(_ value: CoreHourlyWeather) {
let mutable = self.hourly.mutableCopy() as! NSMutableOrderedSet
mutable.add(value)
self.hourly = mutable.copy() as! NSOrderedSet
}
open func removeHourlyObject(_ value: CoreHourlyWeather) {
let mutable = self.hourly.mutableCopy() as! NSMutableOrderedSet
mutable.remove(value)
self.hourly = mutable.copy() as! NSOrderedSet
}
}
// DO NOT EDIT. This file is machine-generated and constantly overwritten.
// Make changes to CorePollutant.swift instead.
import Foundation
import CoreData
public enum CorePollutantAttributes: String {
case name = "name"
case value = "value"
}
public enum CorePollutantRelationships: String {
case health = "health"
}
open class _CorePollutant: NSManagedObject {
// MARK: - Class methods
open class func entityName () -> String {
return "CorePollutant"
}
open class func entity(managedObjectContext: NSManagedObjectContext) -> NSEntityDescription? {
return NSEntityDescription.entity(forEntityName: self.entityName(), in: managedObjectContext)
}
@nonobjc
open class func fetchRequest() -> NSFetchRequest<CorePollutant> {
return NSFetchRequest(entityName: self.entityName())
}
// MARK: - Life cycle methods
public override init(entity: NSEntityDescription, insertInto context: NSManagedObjectContext?) {
super.init(entity: entity, insertInto: context)
}
public convenience init?(managedObjectContext: NSManagedObjectContext) {
guard let entity = _CorePollutant.entity(managedObjectContext: managedObjectContext) else { return nil }
self.init(entity: entity, insertInto: managedObjectContext)
}
// MARK: - Properties
@NSManaged open
var name: String!
@NSManaged open
var value: Double
// MARK: - Relationships
@NSManaged open
var health: CoreHealth?
}
#!/bin/sh
# This project uses the mogenerator tool to generate model objects for CoreData: https://rentzsch.github.io/mogenerator/
# Run this script after changing the CoreData model (1WModel.xcdatamodeld).
# This script should be run from the same directory where the model is located.
MODEL_NAME="1WModel.xcdatamodeld"
if ! [ -e "$MODEL_NAME" ]
then
echo "Please, call this script from the same directory where the model file is located."
exit 1
fi
mogenerator --model "./$MODEL_NAME" \
--swift \
--machine-dir ./Objects/Machine \
--human-dir ./Objects/Human
//
// Storage.swift
// 1Weather
//
// Created by Demid Merzlyakov on 02.04.2021.
//
import Foundation
public typealias StorageCompletion = ([Location]?, Int?, Error?) -> ()
public protocol Storage {
func save(locations: [Location], selectedIndex: Int?)
func load(completion: @escaping StorageCompletion)
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment