im using UIKit delegate to manage app lifecycle but using swiftUI do the UI stuff.
lets say I have following data model entities, and i want to cached it via core data.
class ClassEntity: Codable {
var classTitleName: String
var classRank: Int
var students: [StudentEntity]
var teachers: [TeacherEntity]
init (classTitleName: String,
classRank: Int,
students: [StudentEntity],
teachers: [TeacherEntity]) {
self.classTitleName = classTitleName
self.classRank = classRank
self.students = students
self.teachers = teachers
}
}
class StudentEntity: Codable {
var studentName: String
var studentGender: String
init(studentName: String,
studentGender: String){
self.studentName = studentName
self.studentGender = studentGender
}
}
class TeacherEntity: Codable{
var teacherName: String
var teacherGender: String
init(teacherName: String,
teacherGender: String){
self.teacherName = teacherName
self.teacherGender = teacherGender
}
}
so base on above entities, i created core data entity like following:
Then, lets say i have two viewModel called SaveClassInfoViewModel
FetchCachedClassInfoViewModel
, first one do save and second one do fetch
so the ViewModel will be like :
class SaveClassInfoViewModel: ObservableObject {
var schoolTotalClass: [ClassEntity]
init(schoolTotalClass: [ClassEntity]) {
self.schoolTotalClass = schoolTotalClass // data will be inject from previous VC , lets say we have data there.
}
func saveSchoolTotalClassInfo() {
guard let appDelegate =
UIApplication.shared.delegate as? AppDelegate else {
return
}
let managedContext =
appDelegate.persistentContainer.viewContext
// how should i save data to cache ?
}
}
class FetchCachedClassInfoViewModel: ObservableObject {
@Published var schoolTotalClass: [ClassEntity] = []
func fetchData() {
guard let appDelegate =
UIApplication.shared.delegate as? AppDelegate else {
return
}
let managedContext =
appDelegate.persistentContainer.viewContext
// how should i do fetch so that im able to assign all the stored data to `schoolTotalClass` ?
// if able to assign cached data to @Published wrapped schoolTotalClass?
// once i got data , i can consume `@Published var schoolTotalClass` in view file directly
}
}
how should i do save and fetch there, is my core data entity definition correct ? thanks very much
Rather creating relation like this you can do it saving the class id in teacher and student and get them on the basis of id like as:
class ClassEntity {
let id:String
var classTitleName: String
var classRank: Int
init (id:String,
classTitleName: String,
classRank: Int) {
self.id = id
self.classTitleName = classTitleName
self.classRank = classRank
}
}
then your teacher and student
class StudentEntity {
var classId:String
var studentName: String
var studentGender: String
init(classId:String,studentName: String,
studentGender: String){
self.classId = classId
self.studentName = studentName
self.studentGender = studentGender
}
}
class TeacherEntity {
var classId:String
var teacherName: String
var teacherGender: String
init(classId:String,teacherName: String,
teacherGender: String){
self.classId = classId
self.teacherName = teacherName
self.teacherGender = teacherGender
}
}
then create coredatastack
import Foundation import CoreData
class CoreDataStack: NSObject {
private let modelName: String
lazy var managedContext: NSManagedObjectContext = {
return self.storeContainer.viewContext
}()
init(modelName: String) {
self.modelName = modelName
}
private lazy var storeContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: self.modelName)
container.loadPersistentStores { (storeDescription, error) in
if let error = error as NSError? {
print("Unresolved error \(error), \(error.userInfo)")
}
}
container.viewContext.automaticallyMergesChangesFromParent = true
container.viewContext.mergePolicy = NSMergeByPropertyStoreTrumpMergePolicy
return container
}()
func saveContext () {
guard managedContext.hasChanges else { return }
do {
try managedContext.save()
} catch let error as NSError {
print("Unresolved error \(error), \(error.userInfo)")
}
}
func updateContext() {
do {
try managedContext.save()
} catch let error as NSError {
print("Unresolved error \(error), \(error.userInfo)")
}
}
func clearChanges() {
managedContext.rollback()
}
func deleteReminder(reminder:Reminder) {
managedContext.delete(reminder)
updateContext()
}
func deleteNote(note:Note) {
managedContext.delete(note)
updateContext()
}
func deleteFromIds(selectedId:SubCategoryIds) {
managedContext.delete(selectedId)
updateContext()
}
}
then create a manager
import Foundation
import CoreData
class CoreDataManager {
static let shared = CoreDataManager()
private init(){}
lazy var coreDataStack = CoreDataStack(modelName: "YourModelName")
func allClasses() -> [ClassEntity] {
let fetechRequest: NSFetchRequest<ClassEntity> = ClassEntity.fetchRequest()
do {
let results = try coreDataStack.managedContext.fetch(fetechRequest)
return results
} catch {
}
return [ClassEntity]()
}
func allStudentOfClass(classId:String) -> [StudentEntity] {
let fetechRequest: NSFetchRequest< StudentEntity > = StudentEntity.fetchRequest()
fetechRequest.predicate = NSPredicate(format: "classId == %@",
argumentArray: [classId])
do {
let results = try coreDataStack.managedContext.fetch(fetechRequest)
return results
} catch {
}
return [StudentEntity]()
}
func allTeacherOfClass(classId:String) -> [TeacherEntity] {
let fetechRequest: NSFetchRequest<TeacherEntity> = TeacherEntity.fetchRequest()
fetechRequest.predicate = NSPredicate(format: "classId == %@",
argumentArray: [classId])
do {
let results = try coreDataStack.managedContext.fetch(fetechRequest)
return results
} catch {
}
return [TeacherEntity]()
}
}
how you can create a class
func createClass() {
let id = "Class 1" //or whatever you want to say here
let _class = Class(context: CoreDataManger.shared.coreDataStack.managedContext)
_class.id = id
_class.classTitleName = "Title"
_class.classRank = 12
CoreDataManger.shared.coreDataStack.saveContext()
}
same as how create teacher with this class
func addTeacher(classId:String) {
let _class = TeacherEntity(context: CoreDataManger.shared.coreDataStack.managedContext)
_class.classId = classId
_class.teacherGender = "Male"
_class.teacherName = "Alex"
CoreDataManger.shared.coreDataStack.saveContext()
}