From b689a7bbf1aa6a3413bc51f5afd33a7cf1d5885d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20Mu=CC=88ller?= Date: Wed, 10 Feb 2021 20:26:53 +0100 Subject: [PATCH] :recycle: Refactored CoreData access --- .../Models/Lecturer+CoreDataClass.swift | 19 ++++++ .../Models/RaPlaEvent+CoreDataClass.swift | 19 ++++++ .../CoreData/Models/User+CoreDataClass.swift | 19 ++++++ DHBW-Service/CoreData/Persistence.swift | 63 ++++++++++--------- DHBW-Service/Utility/UtilityFunctions.swift | 1 + DHBW-Service/Views/ContentView.swift | 2 +- .../Views/Other/FirstOpeningSettings.swift | 9 ++- DHBW-Service/Views/Tabs/HomeView.swift | 34 +++++----- DHBW-Service/Views/Tabs/LecturePlanItem.swift | 22 +++---- DHBW-Service/Views/Tabs/LecturePlanList.swift | 16 ++--- 10 files changed, 132 insertions(+), 72 deletions(-) diff --git a/DHBW-Service/CoreData/Models/Lecturer+CoreDataClass.swift b/DHBW-Service/CoreData/Models/Lecturer+CoreDataClass.swift index 22102df..ea7ba96 100644 --- a/DHBW-Service/CoreData/Models/Lecturer+CoreDataClass.swift +++ b/DHBW-Service/CoreData/Models/Lecturer+CoreDataClass.swift @@ -22,4 +22,23 @@ public class Lecturer: NSManagedObject { return [] } } + + @nonobjc public class func getSpecified(sortDescriptors: [NSSortDescriptor] = [], searchPredicate: NSPredicate? = nil) -> [Lecturer]{ + let managedContext = + PersistenceController.shared.context + + let fetchRequest: NSFetchRequest = Lecturer.fetchRequest() + + fetchRequest.sortDescriptors = sortDescriptors + if(searchPredicate != nil) { + fetchRequest.predicate = searchPredicate + } + + do { + return try managedContext.fetch(fetchRequest) + } catch let error as NSError { + print("Could not fetch. \(error), \(error.userInfo)") + return [] + } + } } diff --git a/DHBW-Service/CoreData/Models/RaPlaEvent+CoreDataClass.swift b/DHBW-Service/CoreData/Models/RaPlaEvent+CoreDataClass.swift index 3a56ebc..c553290 100644 --- a/DHBW-Service/CoreData/Models/RaPlaEvent+CoreDataClass.swift +++ b/DHBW-Service/CoreData/Models/RaPlaEvent+CoreDataClass.swift @@ -22,4 +22,23 @@ public class RaPlaEvent: NSManagedObject { return [] } } + + @nonobjc public class func getSpecified(sortDescriptors: [NSSortDescriptor] = [], searchPredicate: NSPredicate? = nil) -> [RaPlaEvent]{ + let managedContext = + PersistenceController.shared.context + + let fetchRequest: NSFetchRequest = RaPlaEvent.fetchRequest() + + fetchRequest.sortDescriptors = sortDescriptors + if(searchPredicate != nil) { + fetchRequest.predicate = searchPredicate + } + + do { + return try managedContext.fetch(fetchRequest) + } catch let error as NSError { + print("Could not fetch. \(error), \(error.userInfo)") + return [] + } + } } diff --git a/DHBW-Service/CoreData/Models/User+CoreDataClass.swift b/DHBW-Service/CoreData/Models/User+CoreDataClass.swift index 0018b5a..a690fc3 100644 --- a/DHBW-Service/CoreData/Models/User+CoreDataClass.swift +++ b/DHBW-Service/CoreData/Models/User+CoreDataClass.swift @@ -22,4 +22,23 @@ public class User: NSManagedObject { return [] } } + + @nonobjc public class func getSpecified(sortDescriptors: [NSSortDescriptor] = [], searchPredicate: NSPredicate? = nil) -> [User]{ + let managedContext = + PersistenceController.shared.context + + let fetchRequest: NSFetchRequest = User.fetchRequest() + + fetchRequest.sortDescriptors = sortDescriptors + if(searchPredicate != nil) { + fetchRequest.predicate = searchPredicate + } + + do { + return try managedContext.fetch(fetchRequest) + } catch let error as NSError { + print("Could not fetch. \(error), \(error.userInfo)") + return [] + } + } } diff --git a/DHBW-Service/CoreData/Persistence.swift b/DHBW-Service/CoreData/Persistence.swift index 8bb986c..088e5cc 100644 --- a/DHBW-Service/CoreData/Persistence.swift +++ b/DHBW-Service/CoreData/Persistence.swift @@ -65,39 +65,42 @@ struct PersistenceController { let viewContext = result.container.viewContext // set mock user - let userEntity = NSEntityDescription.entity(forEntityName: "User", in: PersistenceController.shared.context)! - let user = NSManagedObject(entity: userEntity, insertInto: PersistenceController.shared.context) - user.setValue("Max Mustermann", forKey: "name") - user.setValue("TINF19B4", forKey: "course") - user.setValue("Dr. Mustermann", forKey: "director") + let user = User(context: PersistenceController.shared.context) + user.name = "Max Mustermann" + user.course = "TINF19B4" + user.director = "Prof. Dr. Mustermann" // Generate mock events - let eventEntity = NSEntityDescription.entity(forEntityName: "RaPlaEvent", in: PersistenceController.shared.context)! - let normalEvent1 = NSManagedObject(entity: eventEntity, insertInto: PersistenceController.shared.context) - let normalEvent2 = NSManagedObject(entity: eventEntity, insertInto: PersistenceController.shared.context) - let examEvent = NSManagedObject(entity: eventEntity, insertInto: PersistenceController.shared.context) - normalEvent1.setValue("Mock Event 1", forKey: "summary") - normalEvent2.setValue("Mock Event 2", forKey: "summary") - examEvent.setValue("Exam Event", forKey: "summary") - normalEvent1.setValue("Mock Event 1 Description", forKey: "descr") - normalEvent2.setValue("Mock Event 2 Description", forKey: "descr") - examEvent.setValue("Exam Event Description", forKey: "descr") - normalEvent1.setValue("E207 INF Hörsaal", forKey: "location") - normalEvent2.setValue("A306 WI Hörsaal", forKey: "location") - examEvent.setValue("Audimax A", forKey: "location") - normalEvent1.setValue("Lehrveranstaltung", forKey: "category") - normalEvent2.setValue("Lehrveranstaltung", forKey: "category") - examEvent.setValue("Prüfung", forKey: "category") + let normalEvent1 = RaPlaEvent(context: PersistenceController.shared.context) + let normalEvent2 = RaPlaEvent(context: PersistenceController.shared.context) + let examEvent = RaPlaEvent(context: PersistenceController.shared.context) + normalEvent1.summary = "Mock Event 1" + normalEvent2.summary = "Mock Event 2" + examEvent.summary = "Exam Event" + + normalEvent1.descr = "Mock Event 1 description" + normalEvent2.descr = "Mock Event 2 description" + examEvent.descr = "Exam Event description" + + normalEvent1.location = "E207 INF Hörsaal" + normalEvent2.location = "A306 WI Hörsaal" + examEvent.location = "Audimax A" + + normalEvent1.category = "Lehrveranstaltung" + normalEvent2.category = "Lehrveranstaltung" + examEvent.category = "Prüfung" + var currentDate = Date() - currentDate.addTimeInterval(1*60*60);normalEvent1.setValue(currentDate, forKey: "startDate") - currentDate.addTimeInterval(1*60*60);normalEvent2.setValue(currentDate, forKey: "startDate") - currentDate.addTimeInterval(1*60*60);examEvent.setValue(currentDate, forKey: "startDate") - currentDate.addTimeInterval(1*60*60);normalEvent1.setValue(currentDate, forKey: "endDate") - currentDate.addTimeInterval(1*60*60);normalEvent2.setValue(currentDate, forKey: "endDate") - currentDate.addTimeInterval(1*60*60);examEvent.setValue(currentDate, forKey: "endDate") - normalEvent1.setValue("totalUniqueId1", forKey: "uid") - normalEvent2.setValue("totalUniqueId2", forKey: "uid") - examEvent.setValue("totalUniqueId3", forKey: "uid") + currentDate.addTimeInterval(1*60*60);normalEvent1.startDate = currentDate + currentDate.addTimeInterval(1*60*60);normalEvent2.startDate = currentDate + currentDate.addTimeInterval(1*60*60);examEvent.startDate = currentDate + currentDate.addTimeInterval(1*60*60);normalEvent1.endDate = currentDate + currentDate.addTimeInterval(1*60*60);normalEvent2.endDate = currentDate + currentDate.addTimeInterval(1*60*60);examEvent.endDate = currentDate + + normalEvent1.uid = "totalUniqueId1" + normalEvent2.uid = "totalUniqueId2" + examEvent.uid = "totalUniqueId3" do { diff --git a/DHBW-Service/Utility/UtilityFunctions.swift b/DHBW-Service/Utility/UtilityFunctions.swift index cfead4d..7f39527 100644 --- a/DHBW-Service/Utility/UtilityFunctions.swift +++ b/DHBW-Service/Utility/UtilityFunctions.swift @@ -9,6 +9,7 @@ import Foundation import CoreData class UtilityFunctions { + // DEPRECATED, replaced by the respective getSpecified() method of each CoreData object public class func getCoreDataObject(entity: String, sortDescriptors: [NSSortDescriptor] = [], searchPredicate: NSPredicate? = nil) -> [NSManagedObject]{ let managedContext = PersistenceController.shared.context diff --git a/DHBW-Service/Views/ContentView.swift b/DHBW-Service/Views/ContentView.swift index 7c2908a..cfa4abb 100644 --- a/DHBW-Service/Views/ContentView.swift +++ b/DHBW-Service/Views/ContentView.swift @@ -47,7 +47,7 @@ struct ContentView: View { } .onAppear{ // Called upon the opening of the app - RaPlaFetcher.getRaplaFileAndSaveToCoreData(from: "https://rapla.dhbw-karlsruhe.de/rapla?page=ical&user=eisenbiegler&file=TINF19B4") + RaPlaFetcher.getRaplaFileAndSaveToCoreData(from: "https://rapla.dhbw-karlsruhe.de/rapla?page=ical&user=eisenbiegler&file=TINF20B4") } } } diff --git a/DHBW-Service/Views/Other/FirstOpeningSettings.swift b/DHBW-Service/Views/Other/FirstOpeningSettings.swift index e07133f..68edadf 100644 --- a/DHBW-Service/Views/Other/FirstOpeningSettings.swift +++ b/DHBW-Service/Views/Other/FirstOpeningSettings.swift @@ -96,11 +96,10 @@ extension FirstOpeningSettings{ print("Deleting old user data status: \(status)") // Insert new user data - let entity = NSEntityDescription.entity(forEntityName: "User", in: PersistenceController.shared.context)! - let user = NSManagedObject(entity: entity, insertInto: PersistenceController.shared.context) - user.setValue(name, forKey: "name") - user.setValue(course, forKey: "course") - user.setValue(director, forKey: "director") + let user = User(context: PersistenceController.shared.context) + user.name = name + user.course = course + user.director = director self.settings.isFirstOpening = !self.settings.isFirstOpening PersistenceController.shared.save() diff --git a/DHBW-Service/Views/Tabs/HomeView.swift b/DHBW-Service/Views/Tabs/HomeView.swift index 6eff55c..2765e8d 100644 --- a/DHBW-Service/Views/Tabs/HomeView.swift +++ b/DHBW-Service/Views/Tabs/HomeView.swift @@ -13,9 +13,9 @@ struct HomeView: View { @State private var name: String = "" @State private var course: String = "" @State private var director: String = "" - @State private var todaysEvents: [NSManagedObject] = [] - @State private var tomorrowsEvents: [NSManagedObject] = [] - @State private var upcomingExams: [NSManagedObject] = [] + @State private var todaysEvents: [RaPlaEvent] = [] + @State private var tomorrowsEvents: [RaPlaEvent] = [] + @State private var upcomingExams: [RaPlaEvent] = [] var body: some View { NavigationView { @@ -115,25 +115,25 @@ struct HomeView: View { extension HomeView{ // Read required data from CoreData and save it to the appropriate variables func readFromCoreData() { - let fetchedData = UtilityFunctions.getCoreDataObject(entity: "User") + let fetchedData = User.getAll() if(!fetchedData.isEmpty) { let user = fetchedData[0] - self.name = user.value(forKey: "name") as! String - self.course = user.value(forKey: "course") as! String - self.director = user.value(forKey: "director") as! String + self.name = user.name! + self.course = user.course! + self.director = user.director! } } // Get 0...2 of todays lectures from RaPla // Returns a list of RaPlaEvent NSManagedObjects - func getTodaysEvents() -> [NSManagedObject] { + func getTodaysEvents() -> [RaPlaEvent] { let searchPredicate = NSPredicate(format: "(category == 'Lehrveranstaltung')") let hiddenPredicate = NSPredicate(format: "isHidden == NO") var predicates = [searchPredicate, hiddenPredicate] predicates.append(contentsOf: getDayPredicates(today: true)) let compoundPredicate = NSCompoundPredicate(andPredicateWithSubpredicates: predicates) - let events = UtilityFunctions.getCoreDataObject(entity: "RaPlaEvent", searchPredicate: compoundPredicate) + let events = RaPlaEvent.getSpecified(searchPredicate: compoundPredicate) if(!events.isEmpty) { return Array(events[...min(1, events.count-1)]) } else { @@ -143,13 +143,13 @@ extension HomeView{ // Get 0...2 of tomorrows lectures from RaPla // Returns a list of RaPlaEvent NSManagedObjects - func getTomorrowsEvents() -> [NSManagedObject] { + func getTomorrowsEvents() -> [RaPlaEvent] { let searchPredicate = NSPredicate(format: "(category == 'Lehrveranstaltung')") let hiddenPredicate = NSPredicate(format: "isHidden == NO") var predicates = [searchPredicate, hiddenPredicate] predicates.append(contentsOf: getDayPredicates(tomorrow: true)) let compoundPredicate = NSCompoundPredicate(andPredicateWithSubpredicates: predicates) - let events = UtilityFunctions.getCoreDataObject(entity: "RaPlaEvent", searchPredicate: compoundPredicate) + let events = RaPlaEvent.getSpecified(searchPredicate: compoundPredicate) if(!events.isEmpty) { return Array(events[...min(1, events.count-1)]) } else { @@ -159,13 +159,13 @@ extension HomeView{ // Get 0...2 of upcoming exams from RaPla // Returns a list of RaPlaEvent NSManagedObjects - func getUpcomingExams() -> [NSManagedObject] { + func getUpcomingExams() -> [RaPlaEvent] { let searchPredicate = NSPredicate(format: "category == %@", "Prüfung") let hiddenPredicate = NSPredicate(format: "isHidden == NO") let compoundPredicate = NSCompoundPredicate(andPredicateWithSubpredicates: [searchPredicate, hiddenPredicate]) let sectionSortDescriptor = NSSortDescriptor(key: "startDate", ascending: true) let sortDescriptors = [sectionSortDescriptor] - let events = UtilityFunctions.getCoreDataObject(entity: "RaPlaEvent", sortDescriptors: sortDescriptors, searchPredicate: compoundPredicate) + let events = RaPlaEvent.getSpecified(sortDescriptors: sortDescriptors, searchPredicate: compoundPredicate) if(!events.isEmpty) { return Array(events[...min(1, events.count-1)]) } else { @@ -222,7 +222,7 @@ extension HomeView{ } struct UpcomingLecturesBlock: View { - let eventsList: [NSManagedObject] + let eventsList: [RaPlaEvent] let titleKey: String var body: some View { @@ -233,7 +233,7 @@ struct UpcomingLecturesBlock: View { VStack { if(!eventsList.isEmpty){ ForEach(eventsList, id: \.self) { exam in - Text(exam.value(forKey: "summary") as! String) + Text(exam.summary!) .frame(maxWidth: .infinity, alignment: .leading) } } else { @@ -251,7 +251,7 @@ struct UpcomingLecturesBlock: View { } struct UpcomingExamsBlock: View { - let examsList: [NSManagedObject] + let examsList: [RaPlaEvent] let titleKey: String var body: some View { @@ -262,7 +262,7 @@ struct UpcomingExamsBlock: View { VStack { if(!examsList.isEmpty){ ForEach(examsList, id: \.self) { exam in - Text(exam.value(forKey: "summary") as! String) + Text(exam.summary!) .frame(maxWidth: .infinity, alignment: .leading) } } else { diff --git a/DHBW-Service/Views/Tabs/LecturePlanItem.swift b/DHBW-Service/Views/Tabs/LecturePlanItem.swift index 985e617..4feb7e4 100644 --- a/DHBW-Service/Views/Tabs/LecturePlanItem.swift +++ b/DHBW-Service/Views/Tabs/LecturePlanItem.swift @@ -9,7 +9,7 @@ import SwiftUI import CoreData struct LecturePlanItem: View { - @State var event: NSManagedObject + @State var event: RaPlaEvent @State var isHidden = false var body: some View { @@ -17,10 +17,10 @@ struct LecturePlanItem: View { HStack { Spacer() VStack { - Text(event.value(forKey: "summary") as! String) + Text(event.summary!) .font(.title3) .frame(maxWidth: .infinity, alignment: .leading) - Text(event.value(forKey: "descr") as! String) + Text(event.descr!) .bold() .frame(maxWidth: .infinity, alignment: .leading) Divider() @@ -31,20 +31,20 @@ struct LecturePlanItem: View { Text("Who") } VStack(alignment: .leading) { - Text(getDateAndTimeAsString(date: event.value(forKey: "startDate") as! Date) + Text(getDateAndTimeAsString(date: event.startDate!) + " to " - + getTimeAsString(date: event.value(forKey: "endDate") as! Date)) + + getTimeAsString(date: event.endDate!)) .bold() - Text(event.value(forKey: "location") as! String) + Text(event.location!) .bold() - Text(event.value(forKey: "location") as! String) + Text("WIP") .bold() }.frame(maxWidth: .infinity, alignment: .leading) } Divider() HStack { Button(action: { - event.setValue(!isHidden, forKey: "isHidden") + event.isHidden = !isHidden self.isHidden = !isHidden PersistenceController.shared.save() }){ @@ -72,7 +72,7 @@ struct LecturePlanItem: View { Spacer() } .onAppear{ - self.isHidden = event.value(forKey: "isHidden") as! Bool + self.isHidden = event.isHidden } } } @@ -107,7 +107,7 @@ struct LecturePlanItem_Previews: PreviewProvider { return settings } - static func getPreviewEvent() -> NSManagedObject { - return UtilityFunctions.getCoreDataObject(entity: "RaPlaEvent", sortDescriptors: [])[0] + static func getPreviewEvent() -> RaPlaEvent { + return RaPlaEvent.getSpecified(sortDescriptors: [])[0] } } diff --git a/DHBW-Service/Views/Tabs/LecturePlanList.swift b/DHBW-Service/Views/Tabs/LecturePlanList.swift index cd96d0a..9109066 100644 --- a/DHBW-Service/Views/Tabs/LecturePlanList.swift +++ b/DHBW-Service/Views/Tabs/LecturePlanList.swift @@ -9,7 +9,7 @@ import SwiftUI import CoreData struct LecturePlanList: View { - @State private var events: [NSManagedObject] = [] + @State private var events: [RaPlaEvent] = [] @State private var sortingAscending = true var body: some View { @@ -18,14 +18,14 @@ struct LecturePlanList: View { ForEach(events, id: \.self) { event in NavigationLink(destination: LecturePlanItem(event: event)){ HStack { - Text(formatDate(date: event.value(forKeyPath: "startDate") as! Date)) + Text(formatDate(date: event.startDate!)) .foregroundColor(getEventForegroundColor(for: event)) - Text(event.value(forKeyPath: "summary") as! String) + Text(event.summary!) .foregroundColor(getEventForegroundColor(for: event)) Spacer() - if(event.value(forKey: "isHidden") as! Bool) { + if(event.isHidden) { Image(systemName: "eye.slash") .foregroundColor(.red) } else { @@ -38,7 +38,7 @@ struct LecturePlanList: View { let sectionSortDescriptor = NSSortDescriptor(key: "startDate", ascending: true) let sortDescriptors = [sectionSortDescriptor] self.events = [] - self.events = UtilityFunctions.getCoreDataObject(entity: "RaPlaEvent", sortDescriptors: sortDescriptors) + self.events = RaPlaEvent.getSpecified(sortDescriptors: sortDescriptors) }) } } @@ -61,7 +61,7 @@ struct LecturePlanList: View { let sectionSortDescriptor = NSSortDescriptor(key: "startDate", ascending: true) let sortDescriptors = [sectionSortDescriptor] self.events = [] - self.events = UtilityFunctions.getCoreDataObject(entity: "RaPlaEvent", sortDescriptors: sortDescriptors) + self.events = RaPlaEvent.getSpecified(sortDescriptors: sortDescriptors) } } } @@ -89,9 +89,9 @@ extension LecturePlanList { return formatter.string(from: date) } - private func getEventForegroundColor(for event: NSManagedObject) -> Color { + private func getEventForegroundColor(for event: RaPlaEvent) -> Color { var textColor: Color = .primary - if(event.value(forKeyPath: "category") as! String == "Prüfung") { + if(event.category! == "Prüfung") { textColor = Color.red } else { textColor = Color.primary