DataManager.swift 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. import Foundation
  2. // Fetch Data for Glucose and Determination from Core Data and map them to the Structs in order to pass them thread safe to the glucoseDidUpdate/ pushUpdate function
  3. @available(iOS 16.2, *)
  4. extension LiveActivityManager {
  5. func fetchAndMapGlucose() async throws -> [GlucoseData] {
  6. let results = try await CoreDataStack.shared.fetchEntitiesAsync(
  7. ofType: GlucoseStored.self,
  8. onContext: context,
  9. predicate: NSPredicate.predicateForSixHoursAgo,
  10. key: "date",
  11. ascending: false,
  12. fetchLimit: 72
  13. )
  14. return try await context.perform {
  15. guard let glucoseResults = results as? [GlucoseStored] else {
  16. throw CoreDataError.fetchError(function: #function, file: #file)
  17. }
  18. return glucoseResults.map {
  19. GlucoseData(glucose: Int($0.glucose), date: $0.date ?? Date(), direction: $0.directionEnum)
  20. }
  21. }
  22. }
  23. // TODO: extract logic or at least rename function appropiately
  24. func fetchAndMapDetermination() async throws -> DeterminationData? {
  25. let results = try await CoreDataStack.shared.fetchEntitiesAsync(
  26. ofType: OrefDetermination.self,
  27. onContext: context,
  28. predicate: NSPredicate.predicateFor30MinAgoForDetermination,
  29. key: "deliverAt",
  30. ascending: false,
  31. fetchLimit: 1,
  32. propertiesToFetch: ["cob", "currentTarget", "deliverAt"]
  33. )
  34. let tddResults = try await CoreDataStack.shared.fetchEntitiesAsync(
  35. ofType: TDDStored.self,
  36. onContext: context,
  37. predicate: NSPredicate.predicateFor30MinAgo,
  38. key: "date",
  39. ascending: false,
  40. fetchLimit: 1,
  41. propertiesToFetch: ["total"]
  42. )
  43. return try await context.perform {
  44. guard let determinationResults = results as? [[String: Any]], let tddResults = tddResults as? [[String: Any]] else {
  45. throw CoreDataError.fetchError(function: #function, file: #file)
  46. }
  47. guard let determination = determinationResults.first else {
  48. return nil
  49. }
  50. let tddValue = (tddResults.first?["total"] as? NSDecimalNumber)?.decimalValue ?? 0
  51. return DeterminationData(
  52. cob: (determination["cob"] as? Int) ?? 0,
  53. tdd: tddValue,
  54. target: (determination["currentTarget"] as? NSDecimalNumber)?.decimalValue ?? 0,
  55. date: determination["deliverAt"] as? Date ?? nil
  56. )
  57. }
  58. }
  59. func fetchAndMapTempTarget() async throws -> TempTargetData? {
  60. try await fetchAndMapLatest(
  61. ofType: TempTargetStored.self,
  62. predicate: .predicateForOneDayAgo,
  63. key: "date",
  64. propertiesToFetch: ["enabled", "name", "target", "date", "duration"]
  65. ) { row in
  66. TempTargetData(
  67. isActive: row["enabled"] as? Bool ?? false,
  68. tempTargetName: row["name"] as? String ?? "Temp Target",
  69. date: row["date"] as? Date ?? Date(),
  70. duration: row["duration"] as? Decimal ?? 0,
  71. target: row["target"] as? Decimal ?? 0
  72. )
  73. }
  74. }
  75. func fetchAndMapOverride() async throws -> OverrideData? {
  76. try await fetchAndMapLatest(
  77. ofType: OverrideStored.self,
  78. predicate: .predicateForOneDayAgo,
  79. key: "date",
  80. propertiesToFetch: ["enabled", "name", "target", "date", "duration"]
  81. ) { row in
  82. OverrideData(
  83. isActive: row["enabled"] as? Bool ?? false,
  84. overrideName: row["name"] as? String ?? "Override",
  85. date: row["date"] as? Date ?? Date(),
  86. duration: row["duration"] as? Decimal ?? 0,
  87. target: row["target"] as? Decimal ?? 0
  88. )
  89. }
  90. }
  91. private func fetchAndMapLatest<Entity: NSManagedObject, Output>(
  92. ofType type: Entity.Type,
  93. predicate: NSPredicate,
  94. key: String,
  95. propertiesToFetch: [String],
  96. map: @escaping ([String: Any]) -> Output
  97. ) async throws -> Output? {
  98. let results = try await CoreDataStack.shared.fetchEntitiesAsync(
  99. ofType: type,
  100. onContext: context,
  101. predicate: predicate,
  102. key: key,
  103. ascending: false,
  104. fetchLimit: 1,
  105. propertiesToFetch: propertiesToFetch
  106. )
  107. return try await context.perform {
  108. guard let rows = results as? [[String: Any]] else {
  109. throw CoreDataError.fetchError(function: #function, file: #file)
  110. }
  111. return rows.first.map(map)
  112. }
  113. }
  114. }