parent
7430a3842c
commit
5ea3c3f824
@ -0,0 +1,46 @@ |
|||||||
|
// |
||||||
|
// CoreDataRequests.swift |
||||||
|
// LeCountdown |
||||||
|
// |
||||||
|
// Created by Laurent Morvillier on 26/01/2023. |
||||||
|
// |
||||||
|
|
||||||
|
import Foundation |
||||||
|
|
||||||
|
class CoreDataRequests { |
||||||
|
|
||||||
|
static func getOrCreateActivity(name: String) -> Activity { |
||||||
|
|
||||||
|
let context = PersistenceController.shared.container.viewContext |
||||||
|
let request = Activity.fetchRequest() |
||||||
|
request.predicate = NSPredicate(format: "name like %@", name) |
||||||
|
|
||||||
|
do { |
||||||
|
let results = try context.fetch(request) |
||||||
|
if let activity = results.first { |
||||||
|
return activity |
||||||
|
} |
||||||
|
} catch { |
||||||
|
print("error = \(error)") |
||||||
|
} |
||||||
|
let activity = Activity(context: context) |
||||||
|
activity.name = name |
||||||
|
return activity |
||||||
|
} |
||||||
|
|
||||||
|
static func recordActivity(countdown: Countdown, dateInterval: DateInterval) throws { |
||||||
|
|
||||||
|
guard let activity = countdown.activity else { |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
let context = PersistenceController.shared.container.viewContext |
||||||
|
let record = Record(context: context) |
||||||
|
record.start = dateInterval.start |
||||||
|
record.end = dateInterval.end |
||||||
|
record.activity = activity |
||||||
|
|
||||||
|
try context.save() |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -1,10 +1,20 @@ |
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> |
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> |
||||||
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="21513" systemVersion="22A400" minimumToolsVersion="Automatic" sourceLanguage="Swift" usedWithCloudKit="YES" userDefinedModelVersionIdentifier=""> |
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="21513" systemVersion="22A400" minimumToolsVersion="Automatic" sourceLanguage="Swift" usedWithCloudKit="YES" userDefinedModelVersionIdentifier=""> |
||||||
|
<entity name="Activity" representedClassName="Activity" syncable="YES" codeGenerationType="class"> |
||||||
|
<attribute name="name" attributeType="String" defaultValueString=""/> |
||||||
|
<relationship name="countdowns" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="Countdown" inverseName="activity" inverseEntity="Countdown"/> |
||||||
|
<relationship name="records" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="Record" inverseName="activity" inverseEntity="Record"/> |
||||||
|
</entity> |
||||||
<entity name="Countdown" representedClassName="Countdown" syncable="YES" codeGenerationType="class"> |
<entity name="Countdown" representedClassName="Countdown" syncable="YES" codeGenerationType="class"> |
||||||
<attribute name="duration" attributeType="Double" defaultValueString="0" usesScalarValueType="YES"/> |
<attribute name="duration" attributeType="Double" defaultValueString="0" usesScalarValueType="YES"/> |
||||||
<attribute name="image" optional="YES" attributeType="String"/> |
<attribute name="image" optional="YES" attributeType="String"/> |
||||||
<attribute name="name" optional="YES" attributeType="String"/> |
|
||||||
<attribute name="order" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="YES"/> |
<attribute name="order" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="YES"/> |
||||||
<attribute name="sound" optional="YES" attributeType="Date" usesScalarValueType="NO"/> |
<attribute name="sound" optional="YES" attributeType="Date" usesScalarValueType="NO"/> |
||||||
|
<relationship name="activity" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Activity" inverseName="countdowns" inverseEntity="Activity"/> |
||||||
|
</entity> |
||||||
|
<entity name="Record" representedClassName="Record" syncable="YES" codeGenerationType="class"> |
||||||
|
<attribute name="end" attributeType="Date" defaultDateTimeInterval="696425400" usesScalarValueType="NO"/> |
||||||
|
<attribute name="start" attributeType="Date" defaultDateTimeInterval="696425400" usesScalarValueType="NO"/> |
||||||
|
<relationship name="activity" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Activity" inverseName="records" inverseEntity="Activity"/> |
||||||
</entity> |
</entity> |
||||||
</model> |
</model> |
||||||
@ -0,0 +1,36 @@ |
|||||||
|
// |
||||||
|
// PropertyWrappers.swift |
||||||
|
// LeCountdown |
||||||
|
// |
||||||
|
// Created by Laurent Morvillier on 26/01/2023. |
||||||
|
// |
||||||
|
|
||||||
|
import Foundation |
||||||
|
|
||||||
|
@propertyWrapper |
||||||
|
struct UserDefault<T: Codable> { |
||||||
|
let key: String |
||||||
|
let defaultValue: T |
||||||
|
|
||||||
|
init(_ key: String, defaultValue: T) { |
||||||
|
self.key = key |
||||||
|
self.defaultValue = defaultValue |
||||||
|
} |
||||||
|
|
||||||
|
var wrappedValue: T { |
||||||
|
get { |
||||||
|
|
||||||
|
if let data = UserDefaults.standard.object(forKey: key) as? Data, |
||||||
|
let user = try? JSONDecoder().decode(T.self, from: data) { |
||||||
|
return user |
||||||
|
|
||||||
|
} |
||||||
|
return defaultValue |
||||||
|
} |
||||||
|
set { |
||||||
|
if let encoded = try? JSONEncoder().encode(newValue) { |
||||||
|
UserDefaults.standard.set(encoded, forKey: key) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,40 @@ |
|||||||
|
// |
||||||
|
// RecordsView.swift |
||||||
|
// LeCountdown |
||||||
|
// |
||||||
|
// Created by Laurent Morvillier on 26/01/2023. |
||||||
|
// |
||||||
|
|
||||||
|
import SwiftUI |
||||||
|
|
||||||
|
struct RecordsView: View { |
||||||
|
|
||||||
|
@FetchRequest( |
||||||
|
sortDescriptors: [NSSortDescriptor(keyPath: \Record.start, ascending: false)], |
||||||
|
animation: .default) |
||||||
|
private var records: FetchedResults<Record> |
||||||
|
|
||||||
|
var body: some View { |
||||||
|
|
||||||
|
if records.isEmpty { |
||||||
|
Text("You don't have any recorded activity yet") |
||||||
|
} else { |
||||||
|
List { |
||||||
|
ForEach(records) { record in |
||||||
|
HStack { |
||||||
|
Text(record.activity?.name ?? "no activity") |
||||||
|
Spacer() |
||||||
|
Text(record.details) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
struct RecordsView_Previews: PreviewProvider { |
||||||
|
static var previews: some View { |
||||||
|
RecordsView().environment(\.managedObjectContext, PersistenceController.preview.container.viewContext) |
||||||
|
} |
||||||
|
} |
||||||
Loading…
Reference in new issue