Last active
March 7, 2018 23:11
-
-
Save rpapallas/3b71a291801430b8140d0a98532ef7dc to your computer and use it in GitHub Desktop.
DatabaseManager class for CoreData
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This work is licensed under a Creative Commons | |
// Attribution-ShareAlike 4.0 International License. | |
// © 2016 Rafael Papallas and www.computingstories.com | |
import Foundation | |
import CoreData | |
class DatabaseManager { | |
/// Implements the Singleton Design Pattern | |
static let instance = DatabaseManager() | |
// MARK: - Database Level Properties | |
/// Managed Context for Core Data | |
func managedObjectContext() -> NSManagedObjectContext { | |
return persistentContainer.viewContext | |
} | |
/// Persistent Container because we don't have initialised this project with | |
/// Core Data. | |
private lazy var persistentContainer: NSPersistentContainer = { | |
let container = NSPersistentContainer(name: "Model") | |
print(container.persistentStoreDescriptions) | |
container.loadPersistentStores(completionHandler: { (storeDescription, error) in | |
if let error = error { | |
fatalError("Unresolved error \(error), \(error._userInfo)") | |
} | |
}) | |
return container | |
}() | |
// MARK: - API Level Properties | |
/// Returns all the available contexts in the database if any (nil if there | |
/// are no contexts or something went wrong with the database). | |
var allContexts: [Context]? { | |
return getAllEntries(for: "Context") as? [Context] | |
} | |
/// Returns all the available tasks in the database if any (nil if there | |
/// are no tasks or something went wrong with the database). | |
var allTasks: [Task]? { | |
return getAllEntries(for: "Task") as? [Task] | |
} | |
/// Returns an empty Context object to be populated with data using standard | |
/// syntax and then to be saved to the database: | |
/// | |
/// ``` | |
/// let emptyContext = DatabaseManager.instance.getEmptyContextInstance | |
/// emptyContext.name = "Some name" | |
/// DatabaseManager.instance.saveOrUpdateInstance(emptyContext) | |
/// ``` | |
var getEmptyContextInstance: Context { | |
return getEntityDescriptionNewObject(withEntityName: "Context") as! Context | |
} | |
/// Returns an empty Task object to be populated with data using standard | |
/// syntax and then to be saved to the database: | |
/// | |
/// ``` | |
/// let emptyTask = DatabaseManager.instance.getEmptyContextInstance | |
/// emptyTask.title = "Some title" | |
/// DatabaseManager.instance.saveOrUpdateInstance(emptyTask) | |
/// ``` | |
var getEmptyTaskInstance: Task { | |
return getEntityDescriptionNewObject(withEntityName: "Task") as! Task | |
} | |
// MARK: - General purpose functions exposed to the programmer | |
/// Saves or Updates the given instance to the database. | |
/// | |
/// If you retrieved a class instance from this class and you edit it's | |
/// attributes and then used this function, then this method will perform | |
/// update. | |
/// | |
/// If you however, requested an empty class instance from this class and you | |
/// added data to it's attributes, then this method will perform insertion. | |
/// | |
/// - Attributes: | |
/// - instance: The instance to be added/updated. | |
/// | |
/// - Returns: True if the operation was successful, false otherwise. | |
func saveOrUpdate(instance: NSManagedObject) -> Bool { | |
do { | |
try instance.managedObjectContext?.save() | |
return true | |
} catch { | |
fatalError("Failed: \(error)") | |
} | |
return false | |
} | |
/// Returns all the tasks that their estimated time is less than the given | |
/// estimated time. | |
/// | |
/// - Parameters: | |
/// - withEstimatedTimeLessThan: The estimated time to be filtered with | |
/// | |
/// - Returns: A list of tasks which meet the predicate. | |
func filteredTasks(withEstimatedTimeLessThan estimatedTime: Int) -> [Task]? { | |
let tasksFetch: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest(entityName: "Task") | |
tasksFetch.predicate = NSPredicate(format: "estimatedTime <= %@", "\(estimatedTime)") | |
do { | |
let fetchedTasks = try managedObjectContext().fetch(tasksFetch) | |
return fetchedTasks as? [Task] | |
} | |
catch { | |
fatalError("Failed to fetch tasks: \(error)") | |
} | |
return nil | |
} | |
/// Returns a list of tasks for the given context (if any). | |
/// | |
/// - Parameters: | |
/// - context: Context to filter the tasks from. | |
/// | |
/// - Returns: A list of tasks that have the given location assigned to it. | |
func tasksBy(context: Context) -> [Task]? { | |
let tasksFetch: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest(entityName: "Task") | |
tasksFetch.predicate = NSPredicate(format: "hasContext == %@", context) | |
do { | |
let fetchedTasks = try managedObjectContext().fetch(tasksFetch) | |
return fetchedTasks as? [Task] | |
} | |
catch { | |
fatalError("Failed to fetch tasks: \(error)") | |
} | |
return nil | |
} | |
/// Deletes the given instance from the database. | |
/// | |
/// | |
/// An instance provided as an argument is going to be deleted | |
/// and then the rest of the instances would be saved | |
/// | |
/// - Attributes: | |
/// - instance: The instance to be deleted. | |
/// | |
/// - Returns: True if the operation was successful, false otherwise. | |
func delete(instance: NSManagedObject) -> Bool { | |
self.managedObjectContext().delete(instance) | |
do{ | |
try self.managedObjectContext().save() | |
return true | |
} | |
catch{ | |
fatalError("Failed to save the tasks: \(error)") | |
} | |
return false | |
} | |
// MARK: - Private methods for the purpose of this class. | |
/// This will return a new `insertNewObject` instance of type NSManagedObject | |
/// that can be casted down into Context, Location or Task and then to be | |
/// used to create a new record to the database. | |
private func getEntityDescriptionNewObject(withEntityName name: String) -> NSManagedObject { | |
return NSEntityDescription.insertNewObject(forEntityName: name, into: managedObjectContext()) | |
} | |
/// Function used to retrieve all the available records of the given Entity. | |
/// This code is applicable to allContexts, allTasks and allLocations therefore | |
/// wrapped into a single method for reuse. | |
/// | |
/// - Parameters: | |
/// - for: The name of the Entity to query. | |
/// | |
/// - Returns: Results (Any) or nil if nothing found or something went wrong | |
private func getAllEntries(for name: String) -> Any? { | |
let fetch: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest(entityName: name) | |
do { | |
return try managedObjectContext().fetch(fetch) | |
} | |
catch { | |
fatalError("Failed to fetch tasks: \(error)") | |
} | |
return nil | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment