Core Data Master Course

Entity = table
attribute = field

When coding:
import CoreData

You can get CodeGen (click on the inspector of the entity) to manual/none.
When you do that, the type for each row in the database is NSManagedObject
Editor - create NSManagedObject subclass

If you edit an attribute, remember to clean the project

Accessing the data
As a class variable:
var managedObjectContext = NSManagedObjectContext()

When calling on the datasource, for instancing, in view did load:
let appDelegate = UIApplication.shared.delegate as! AppDelegate
        managedObjectContext = appDelegate.persistentContainer.viewContext

Loading the data into a table
var results = [Grocery]()
        let request: NSFetchRequest<Grocery> = Grocery.fetchRequest()

        do
        {
            results = try managedObjectContext.fetch(request)
            groceries = results
            tableView.reloadData()
        }catch{fatalError("Error in retrieving grocery item")}


Storing the data:
let theGrocery = Grocery(context: self.managedObjectContext)
            theGrocery.item = itemStringYouWantToStore
            do
            {
                try self.managedObjectContext.save()
            }catch{fatalError("Error in storing data")}
            //call function to load data again so as to refresh table
            self.loadData()

Accessing the data:
//individual NSManagedObject inside the array groceries:
        let grocery = self.groceries[indexPath.row]
        //getting the value of the item attribute from each grocery object
        cell.textLabel?.text = grocery.item

Adding images to the entity
Binary data type (can be image, pdf, etc)
Allow external storage

Relationships
If there is a relationship between entities:
Let's say there is a relationship between Home and Sales History.
Add a relationship to Home - type: Sales History.
Add a relationship to Sales History - type Home.
Let's say that one home can have many sales history and one sales history can only have one home.
Go to home and select the relationship. Change the relationship type to 'to many'.
The Sales History will be a property of type NSSet in Home.

Subclass:
I have three entities: 
Home, Condo and SingleFamily.
Condo and SingleFamily are subclasses of the Home.
Both Condo and SingleFamily have attributes inherited from Home.
However, I do not need to create these attributes in Condo and Single Family.
Set the parent entity to be 'Home' for both the Condo and Single Family.

Inspecting relationships
You can see the graph of the relationships by clicking on the 3 rectangle diagram at the bottom right hand side of the screen.


Check that the entities are empty, making sure that it is not populated again.
In AppDelegate.swift:
func checkDataStore()
    {
        let request: NSFetchRequest<Home> = Home.fetchRequest()
        let moc = self.persistentContainer.viewContext
        do
        {
            let homeCount = try moc.count(for: request)
            if homeCount == 0
            {
                
            }
        }catch{fatalError("Error in counting home records")}
        
    }

Deleting data
   let taskToDelete = tasks[indexPath.row]
            context.delete(taskToDelete)
            (UIApplication.shared.delegate as! AppDelegate).saveContext()
            //fetch data again and reload table
            do
            {
                try tasks = context.fetch(Task.fetchRequest())
            }catch{}

Search and filter through records
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
        
        do
        {
            let filteredreq : NSFetchRequest<Task> = Task.fetchRequest()
//this means that the attribute nameOfTask contains something
            filteredreq.predicate = NSPredicate(format: "nameOfTask contains[c] %@", searchText)
//the array task of type Task will be populated
            tasks = try context.fetch(filteredreq)
            
        }catch{print(error.localizedDescription)}
    }
Predicate: filter for exact search:
            filteredreq.predicate = NSPredicate(format: "nameOfTask == %@", searchText)
if using predicate on a number:
        request.predicate = NSPredicate(format: "aClassID == %@", cid as NSNumber)

More than one filter
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
        
            do
            {
                let filteredreq : NSFetchRequest<Task> = Task.fetchRequest()
                
                let namePredicate = NSPredicate(format: "nameOfTask contains[c] %@", searchText)
                let imptPredicate = NSPredicate(format: "isImportant == %@", theSwitch.isOn as CVarArg)
                let andPredicate = NSCompoundPredicate(type: .and, subpredicates: [namePredicate, imptPredicate])
                filteredreq.predicate = andPredicate
                tasks = try context.fetch(filteredreq)
                
            }catch{print(error.localizedDescription)}
        
Update data
You have to apply a search,
 let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
        
        do
        {
            var thisText = ""
            if(previousText != nil)
            {
                thisText = previousText!
            }
            
            let filteredreq : NSFetchRequest<Task> = Task.fetchRequest()
            //this means that the attribute nameOfTask contains something
            filteredreq.predicate = NSPredicate(format: "nameOfTask == %@", thisText)
            //the array task of type Task will be populated
            tasks = try context.fetch(filteredreq)
            
            if(tasks.count > 0)
            {
                let newTask = tasks[0]
//getting the values from the textfield and the switch
                newTask.setValue(toUpdateTF.text, forKey: "nameOfTask")
                newTask.setValue(toUpdateSW.isOn, forKey: "isImportant")
                try context.save()
                
            }
        }catch{print(error.localizedDescription)}

Getting a unique key (like taskID) and increasing by 1
//put this in a separate method from the one where you have to add a new task
        let appDelegate = UIApplication.shared.delegate as! AppDelegate
        moc = appDelegate.persistentContainer.viewContext
        var newTaskID: Int16
        newTaskID = 1
        let request: NSFetchRequest<Task> = Task.fetchRequest()
        request.fetchLimit = 1
        let sortDes = NSSortDescriptor(key: "taskID", ascending: false)
        request.sortDescriptors = [sortDes]
        do
        {
            let latestTask = try moc.fetch(request)
            if latestTask.count > 0
            {
            let latestTaskTwo = latestTask.first
                newTaskID = latestTaskTwo?.value(forKey: "taskID") as! Int16
                newTaskID += 1
            }
            
      }catch{}

Getting today's date (with only day, month and year) and convert to NSDate to be stored in database
func getTodaysDate() -> NSDate
    {
        let dc = Calendar(identifier: .gregorian).dateComponents([.day, .month, .year], from: Date())
       
        var dct = DateComponents()
       
        dct.day = dc.day
       
        dct.month = dc.month
       
        dct.year = dc.year
       
       
        let theNewDate = Calendar(identifier: .gregorian).date(from: dct)
       
        let returnDate = theNewDate! as NSDate
       
        return returnDate
    }

Comments

Popular posts from this blog

Setting up a playground

Go to another page