Last active
February 12, 2016 18:18
-
-
Save mingsai/a5b0fb7a9aa2798eebb3 to your computer and use it in GitHub Desktop.
A data store class to manage extended data operations within a separate controller. Notifications pass relevant messages to observers.
This file contains 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
// | |
// DataStore.swift | |
// | |
// | |
// Created by Tommie N. Carter, Jr., MBA on 6/18/15. | |
// Copyright (c) 2015 MING Technology. All rights reserved. | |
// Updated 7/6/2015 | |
// Swift 2.0 compatible | |
import Foundation | |
import CoreData | |
//GUID - https://developer.apple.com/library/mac/documentation/CoreFoundation/Reference/CFUUIDRef/index.html | |
//data notifications | |
//struct MNGDataEvents { | |
// .... | |
//} | |
//Holds the URIRepresentation() of saved objects in DBDataStore.sharedInstance returned via active NSManagedObjectID | |
//struct ActiveRecord { | |
// ... | |
//} | |
var defaultUserRecordID : NSManagedObjectID! | |
var defaultUserID = String() | |
extension NSManagedObject { | |
/* Returns the classname in Swift without the module prepended to it | |
* Previous implementation: return "\(obj)" | |
*/ | |
class var className: String { | |
get { | |
let obj: AnyObject = self as AnyObject | |
return "\(obj)".componentsSeparatedByString(".").last! as String | |
} | |
} | |
/* Returns the classname in Swift without the module prepended to it | |
* Previous implementation: return self.entity.name! | |
*/ | |
var className: String? { | |
get { | |
return self.entity.name!.componentsSeparatedByString(".").last! as String | |
} | |
} | |
/* Creates an instance of the Entity in the managed object context | |
* | |
* Usage: | |
* eg. var item = CustomEntity.createInStore(DBDataStore.sharedInstance) as! CustomEntity | |
* | |
*/ | |
class func createInStore(store: DataStore) -> NSManagedObject { | |
let className = self.className | |
return NSEntityDescription.insertNewObjectForEntityForName(className, inManagedObjectContext: store.context!) as NSManagedObject | |
} | |
/* Finds the entity in the MOC if it exists using the objectID | |
* | |
* Usage: | |
* eg. var items = CustomEntity.findInStore(DBDataStore.sharedInstance, objectID:value) as? | |
* [CustomEntity] | |
*/ | |
class func findInStore(store: DataStore, objectID: NSManagedObjectID) -> AnyObject? { | |
return store.context?.objectWithID(objectID) | |
} | |
/* Finds an array of entities in the MOC if any exists using an optional | |
* predicate and an optional array of sort descriptors | |
* | |
* Usage: | |
* eg. var items = CustomEntity.findInStore(DBDataStore.sharedInstance, sortDescriptors: | |
* [NSSortDescriptor(key: "somekey", ascending: true),...], predicate: | |
* NSPredicate(format: "attribute = %@", someValue)) as? | |
* [CustomEntity] | |
*/ | |
class func findInStore(store: DataStore, sortDescriptors: [NSSortDescriptor]?, predicate: NSPredicate?) -> [AnyObject]? { | |
let className = self.className | |
let fetchRequest = NSFetchRequest(entityName: className) | |
fetchRequest.fetchBatchSize = 20 | |
if (predicate != nil) { | |
fetchRequest.predicate = predicate | |
} | |
if (sortDescriptors != nil) { | |
fetchRequest.sortDescriptors = sortDescriptors | |
} | |
//var error: NSErrorPointer = nil | |
var results :[AnyObject]? | |
do { | |
try | |
results = store.context?.executeFetchRequest(fetchRequest) | |
} catch { | |
//handle errors | |
print (error) | |
return nil | |
} | |
//defaultCenter.postNotificationName(AppDataEvents.DataFoundLocal, object: nil) | |
return results | |
} | |
/* Finds an array of entity in the MOC if any exists | |
* | |
* Usage: | |
* eg. var items = CustomEntity.findInStore(DBDataStore.sharedInstance) as? [CustomEntity] | |
*/ | |
class func findInStore(store: DataStore) -> [AnyObject]? { | |
return findInStore(store, sortDescriptors: nil, predicate: nil) | |
} | |
/* Finds an array of entity in the MOC if any exists using an optional | |
* predicate. | |
* | |
* Usage: | |
* eg. var items = CustomEntity.findInStore(DBDataStore.sharedInstance, predicate: | |
* NSPredicate(format: "attribute = %@", someValue)) as? [CustomEntity] | |
*/ | |
class func findInStore(store: DataStore, predicate: NSPredicate?) -> [AnyObject]? { | |
return findInStore(store, sortDescriptors:nil, predicate:predicate) | |
} | |
/* Finds an array of entity in the MOC if any exists using an optional | |
* predicate. | |
* | |
* Replaces: | |
* let predicate = NSPredicate(format:format, argumentArray:arguments) | |
* | |
* Usage: | |
* eg. var items = CustomEntity.findInStore(DBDataStore.sharedInstance, predicate: | |
* NSPredicate(format: "%@ = %@", arguments)) as? [CustomEntity] | |
*/ | |
class func findInStore(store: DataStore, format: String, arguments: AnyObject ...) -> [AnyObject]? { | |
let predicate = NSPredicate(format:format, arguments) | |
return findInStore(store, sortDescriptors:nil, predicate:predicate) | |
} | |
/* Finds an array of entity in the MOC if any exists using an optional | |
* predicate and any number of variable arguments | |
* | |
* Usage: | |
* eg. var items = CustomEntity.findInStore(DBDataStore.sharedInstance, predicate: | |
* NSPredicate(format: "(attributeName IN %@)", | |
* arguments: "value1","value2","value3",...)) as? | |
* [CustomEntity] | |
* | |
* Replaces: | |
* let predicate = NSPredicate(format:format, argumentArray:arguments) | |
* | |
* More Info: | |
* http://www.cocoawithlove.com/2009/05/variable-argument-lists-in-cocoa.html | |
*/ | |
class func findInStore(store: DataStore, sortDescriptors:[NSSortDescriptor]?, format: String, arguments: CVaListPointer) -> [AnyObject]? { | |
let predicate = NSPredicate(format: format, arguments: arguments) | |
return findInStore(store, sortDescriptors:sortDescriptors, predicate:predicate) | |
} | |
/* Finds an array of entity in the MOC if any exists using an optional | |
* predicate with an array of arguments | |
* | |
* Usage: | |
* eg. var items = CustomEntity.findInStore(DBDataStore.sharedInstance, predicate: | |
* NSPredicate(format: "(%K != %@ AND %K = %@)", argumentArray:["key1","value1","key2","value2"])) | |
* as? [CustomEntity] | |
*/ | |
class func findInStore(store: DataStore, format: String, argumentArray: [AnyObject]?) -> [AnyObject]? { | |
let predicate = NSPredicate(format: format, argumentArray: argumentArray) | |
return findInStore(store, sortDescriptors:nil, predicate:predicate) | |
} | |
class func findOneInStore(store: DataStore, format: String, arguments: AnyObject ...) -> AnyObject? { | |
let results = self.findInStore(store, format: format, arguments: arguments) | |
if (results != nil && results?.count > 0) { | |
return results?[0] | |
} | |
else { | |
return nil | |
} | |
} | |
func removeFromStore() { | |
self.managedObjectContext!.deleteObject(self); | |
} | |
class func removeFromStore(store: DataStore) { | |
if let items:[AnyObject]? = self.findInStore(store) { | |
for item in items! { | |
store.context!.deleteObject(item as! NSManagedObject) | |
} | |
} | |
} | |
} | |
@objc class DataStore:NSObject { | |
private struct Constants { | |
static let DefaultUserID = "DefaultUserID" | |
} | |
final var modelName: String = "" | |
//final var persistentStoreCoordinator: NSPersistentStoreCoordinator? = nil | |
final lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator = { | |
// The persistent store coordinator for the application. This implementation creates and return a coordinator, having added the store for the application to it. This property is optional since there are legitimate error conditions that could cause the creation of the store to fail. | |
// Create the coordinator and store | |
let coordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel) | |
let options = [NSMigratePersistentStoresAutomaticallyOption:NSNumber(bool: true), NSInferMappingModelAutomaticallyOption:NSNumber(bool: true)] | |
let url = self.applicationDocumentsDirectory.URLByAppendingPathComponent("\(self.modelName).sqlite") | |
var failureReason = "There was an error creating or loading the application's saved data." | |
do { | |
try coordinator.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: options) | |
} catch { | |
// Report any error we got. | |
var dict = [String: AnyObject]() | |
dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data" | |
dict[NSLocalizedFailureReasonErrorKey] = failureReason | |
dict[NSUnderlyingErrorKey] = error as NSError | |
let wrappedError = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict) | |
// Replace this with code to handle the error appropriately. | |
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. | |
NSLog("Unresolved error \(wrappedError), \(wrappedError.userInfo)") | |
abort() | |
} | |
return coordinator | |
}() | |
init(modelName: String) { | |
self.modelName = modelName | |
} | |
func initPersistentStore() { | |
_ = self.persistentStoreCoordinator | |
} | |
// | |
// Send back the managedObjectContext for more detailed operations. | |
// | |
//1 | |
final var context: NSManagedObjectContext? { | |
get { | |
// let coordinator = self.persistentStoreCoordinator | |
// let managedObjectContext = NSManagedObjectContext(concurrencyType: .MainQueueConcurrencyType) | |
// managedObjectContext.persistentStoreCoordinator = coordinator | |
return self.managedObjectContext | |
} | |
} | |
final lazy var applicationDocumentsDirectory: NSURL = { | |
let urls = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask) | |
return urls[urls.count-1] as NSURL | |
}() | |
//2 | |
final lazy var managedObjectModel: NSManagedObjectModel = { | |
// The managed object model for the application. This property is not optional. It is a fatal error for the application not to be able to find and load its model. | |
let modelURL = NSBundle.mainBundle().URLForResource(self.modelName, withExtension: "momd")! // | |
return NSManagedObjectModel(contentsOfURL: modelURL)! | |
// if let m = NSManagedObjectModel(contentsOfURL: modelURL) { | |
// return m | |
// } else { | |
// return NSManagedObjectModel.mergedModelFromBundles(nil)! | |
// } | |
}() | |
var pwc:NSManagedObjectContext? = nil | |
final lazy var privateWriterContext:NSManagedObjectContext = { | |
let coordinator = self.persistentStoreCoordinator | |
//Create a writer MOC so all Core Data writes occur on background thread | |
if self.pwc == nil { | |
var _pwc = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType) | |
_pwc.persistentStoreCoordinator = coordinator | |
self.pwc = _pwc | |
} | |
return self.pwc! | |
}() | |
var moc:NSManagedObjectContext? = nil | |
final lazy var managedObjectContext: NSManagedObjectContext = { | |
// Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.) This property is optional since there are legitimate error conditions that could cause the creation of the context to fail. | |
//uses the parent context coordinator | |
//let coordinator = self.persistentStoreCoordinator | |
if self.moc == nil { | |
var managedObjectContext = NSManagedObjectContext(concurrencyType: .MainQueueConcurrencyType) | |
//Assign the writer MOC as the parent of the moc on the main thread ~ forces all saves to the background thread ~ requires specific performBlock save on each context | |
if managedObjectContext.parentContext == nil { | |
managedObjectContext.parentContext = self.privateWriterContext | |
} | |
self.moc = managedObjectContext | |
} | |
//managedObjectContext.undoManager = nil | |
//Since PSC is set on parent it is not needed on any other MOC | |
//managedObjectContext.persistentStoreCoordinator = coordinator | |
return self.moc! | |
}() | |
// all-in-one-solution | |
// lazy var managedObjectContext: NSManagedObjectContext = { | |
// let modelURL = NSBundle.mainBundle().URLForResource("ths", withExtension: "momd") | |
// let mom = NSManagedObjectModel(contentsOfURL: modelURL) | |
// ZAssert(mom != nil, "Error initializing mom from: \(modelURL)") | |
// | |
// let psc = NSPersistentStoreCoordinator(managedObjectModel: mom) | |
// | |
// let urls = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask) | |
// let storeURL = (urls[urls.endIndex-1]).URLByAppendingPathComponent("SwiftTestOne.sqlite") | |
// | |
// var error: NSError? = nil | |
// | |
// var store = psc.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: storeURL, options: nil, error: &error) | |
// if (store == nil) { | |
// println("Failed to load store") | |
// } | |
// ZAssert(store != nil, "Unresolved error \(error?.localizedDescription), \(error?.userInfo)\nAttempted to create store at \(storeURL)") | |
// | |
// var managedObjectContext = NSManagedObjectContext() | |
// managedObjectContext.persistentStoreCoordinator = psc | |
// | |
// return managedObjectContext | |
// }() | |
// lazy var managedObjectContext: NSManagedObjectContext? = { | |
// self.initPersistentStore() | |
// | |
// let coordinator = self.persistentStoreCoordinator | |
// if coordinator == nil { | |
// return nil | |
// } | |
// var managedObjectContext = NSManagedObjectContext() | |
// managedObjectContext.persistentStoreCoordinator = coordinator | |
// return managedObjectContext | |
// }() | |
// MARK: - Core Data Saving support | |
func saveContext () { | |
if managedObjectContext.hasChanges { | |
self.managedObjectContext.performBlock({ () -> Void in | |
do { | |
try self.managedObjectContext.save() | |
} catch let e as NSError { | |
print(e.localizedDescription) | |
} | |
//save the changes to disk | |
dbStore.sharedInstance.privateWriterContext.performBlock({ () -> Void in | |
do { | |
try self.privateWriterContext.save() | |
} catch let e as NSError { | |
print(e.localizedDescription) | |
} | |
}) | |
}) | |
} | |
// if managedObjectContext.hasChanges { | |
// do { | |
// try self.managedObjectContext.save() | |
// defaultCenter.postNotificationName(MNGDataEvents.DataSaved, object: nil) | |
// } catch { | |
// // Replace this implementation with code to handle the error appropriately. | |
// // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. | |
// let nserror = error as NSError | |
// NSLog("Unresolved error \(nserror), \(nserror.userInfo)") | |
// abort() | |
// } | |
// } | |
} | |
@objc class MemoryDataStore: DataStore { | |
override init(modelName:String) { | |
super.init(modelName: modelName) | |
} | |
override func initPersistentStore() { | |
do { | |
let coordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel) | |
let options = [NSMigratePersistentStoresAutomaticallyOption:NSNumber(bool: true), NSInferMappingModelAutomaticallyOption:NSNumber(bool: true)] | |
try coordinator.addPersistentStoreWithType(NSInMemoryStoreType, configuration: nil, URL: nil, options: options) | |
persistentStoreCoordinator = coordinator | |
} catch { | |
let dict = NSMutableDictionary() | |
dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data" | |
//dict[NSLocalizedFailureReasonErrorKey] = failureReason | |
dict[NSUnderlyingErrorKey] = error as NSError | |
//internalError = NSError(domain: self.modelName, code: 9999, userInfo: dict as [NSObject : AnyObject]!) | |
// Replace this with code to handle the error appropriately. | |
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. | |
//println("Unresolved error \(error), \(error!.userInfo)") | |
//abort() | |
} | |
} | |
} | |
} | |
typealias dbStore = DBDataStore | |
@objc class DBDataStore: DataStore { | |
final var databaseName: String = "" | |
static let sharedInstance = DBDataStore(modelName: "ths", databaseName: "ths") | |
@objc | |
init(modelName: String, databaseName: String) { | |
super.init(modelName: modelName) | |
self.databaseName = databaseName | |
} | |
override func initPersistentStore() { | |
do { | |
let coordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel) | |
let url = self.applicationDocumentsDirectory.URLByAppendingPathComponent(self.databaseName + ".sqlite") | |
// | |
// Setup automatic migrations | |
// | |
let options = [NSMigratePersistentStoresAutomaticallyOption: NSNumber(bool: true), | |
NSInferMappingModelAutomaticallyOption : NSNumber(bool:true)] | |
try coordinator.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: options) | |
} catch { | |
// Report any error we got. | |
var dict = [String: AnyObject]() | |
dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data" | |
//dict[NSLocalizedFailureReasonErrorKey] = failureReason | |
dict[NSUnderlyingErrorKey] = error as NSError | |
let wrappedError = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict) | |
// Replace this with code to handle the error appropriately. | |
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. | |
NSLog("Unresolved error \(wrappedError), \(wrappedError.userInfo)") | |
abort() | |
} | |
} | |
//MARK: Helper Methods | |
class func createUUIDForDefaultUser() { | |
if NSUserDefaults.standardUserDefaults().objectForKey(Constants.DefaultUserID) == nil { | |
let uid = NSUUID().UUIDString | |
defaultUserID = uid | |
NSUserDefaults.standardUserDefaults().setObject(uid, forKey: Constants.DefaultUserID) | |
} else if let value = NSUserDefaults.standardUserDefaults().valueForKey(Constants.DefaultUserID) as? String where value.characters.count > 0 { | |
defaultUserID = value | |
} | |
} | |
// func migrateStore(storeURL: NSURL, toVersionTwoStore dstStoreURL: NSURL, error outError: NSError) -> Bool { | |
// var mappingModel: NSMappingModel = NSMappingModel.inferredMappingModelForSourceModel(self.managedObjectModel, destinationModel: self.destinationModel(), error: outError) | |
// if !mappingModel { | |
// return false | |
// } | |
// var classValue: NSValue = NSPersistentStoreCoordinator.registeredStoreTypes().objectForKey(NSSQLiteStoreType) | |
// var sqliteStoreClass: AnyClass = classValue.pointerValue | |
// var sqliteStoreMigrationManagerClass: AnyClass = sqliteStoreClass.migrationManagerClass() | |
// var manager: NSMigrationManager = sqliteStoreMigrationManagerClass(sourceModel: self.sourceModel(), destinationModel: self.destinationModel()) | |
// var success: Bool = manager.migrateStoreFromURL(storeURL, type: NSSQLiteStoreType, options: nil, withMappingModel: mappingModel, toDestinationURL: dstStoreURL, destinationType: NSSQLiteStoreType, destinationOptions: nil, error: outError) | |
// return success | |
// } | |
} | |
//extension DBDataStore:NSFetchedResultsControllerDelegate { | |
// | |
//} | |
//allocate the DBDataStore.sharedInstance | |
//let DBDataStore.sharedInstance = DBDataStore(modelName: "ths", databaseName: "ths") |
This file contains 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
// | |
// MNGDataStore.swift | |
// | |
// | |
// Created by Tommie N. Carter, Jr., MBA on 6/18/15. | |
// Copyright (c) 2015 MING Technology. All rights reserved. | |
// Swift 2.0 compatible | |
// Usage: Type.createInStore (dbStore)... | |
import Foundation | |
import CoreData | |
//let appDelegate:UIApplicationDelegate = UIApplication.sharedApplication().delegate as! AppDelegate | |
//GUID - https://developer.apple.com/library/mac/documentation/CoreFoundation/Reference/CFUUIDRef/index.html | |
//data notifications | |
struct AppDataEvents { | |
//Data | |
static let DataLoaded = "DataStore.DataLoaded" | |
static let DataSaved = "DataStore.DataSaved" | |
static let DataDeleted = "DataStore.DataDeleted" | |
static let DataFoundLocal = "DataStore.DataFoundLocal" | |
//Picture | |
static let PhotoSaved = "YCameraViewController.PhotoSaved" | |
static let PhotoDeleted = "YCameraViewController.PhotoDeleted" | |
//Video | |
//Written | |
//Audio | |
//User | |
//Author | |
} | |
//Holds the URIRepresentation() of saved objects in dbStore returned via active NSManagedObjectID | |
struct ActiveRecord { | |
static var AudioStoryID:NSURL? | |
static var AuthorID:NSURL? | |
static var PictureStoryID:NSURL? | |
static var UserID:NSURL? | |
static var VideoStoryID:NSURL? | |
static var WrittenStoryID:NSURL? | |
} | |
extension NSManagedObject { | |
/* Returns the classname in Swift without the module prepended to it | |
* Previous implementation: return "\(obj)" | |
*/ | |
class var className: String { | |
get { | |
let obj: AnyObject = self as AnyObject | |
return "\(obj)".componentsSeparatedByString(".").last! as String | |
} | |
} | |
/* Returns the classname in Swift without the module prepended to it | |
* Previous implementation: return self.entity.name! | |
*/ | |
var className: String? { | |
get { | |
return self.entity.name!.componentsSeparatedByString(".").last! as String | |
} | |
} | |
/* Creates an instance of the Entity in the managed object context | |
* | |
* Usage: | |
* eg. var item = CustomEntity.createInStore(dbStore) as! CustomEntity | |
* | |
*/ | |
class func createInStore(store: DataStore) -> NSManagedObject { | |
let className = self.className | |
return NSEntityDescription.insertNewObjectForEntityForName(className, inManagedObjectContext: store.context!) as NSManagedObject | |
} | |
/* Finds the entity in the MOC if it exists using the objectID | |
* | |
* Usage: | |
* eg. var items = CustomEntity.findInStore(dbStore, objectID:value) as? | |
* [CustomEntity] | |
*/ | |
class func findInStore(store: DataStore, objectID: NSManagedObjectID) -> NSManagedObject? { | |
return store.context!.objectWithID(objectID) | |
} | |
/* Finds an array of entities in the MOC if any exists using an optional | |
* predicate and an optional array of sort descriptors | |
* | |
* Usage: | |
* eg. var items = CustomEntity.findInStore(dbStore, sortDescriptors: | |
* [NSSortDescriptor(key: "somekey", ascending: true),...], predicate: | |
* NSPredicate(format: "attribute = %@", someValue)) as? | |
* [CustomEntity] | |
*/ | |
class func findInStore(store: DataStore, sortDescriptors: [NSSortDescriptor]?, predicate: NSPredicate?) -> [AnyObject]? { | |
let className = self.className | |
let fetchRequest = NSFetchRequest(entityName: className) | |
if (predicate != nil) { | |
fetchRequest.predicate = predicate | |
} | |
if (sortDescriptors != nil) { | |
fetchRequest.sortDescriptors = sortDescriptors | |
} | |
//var error: NSErrorPointer = nil | |
var results :[AnyObject]? | |
do { | |
try | |
results = store.context?.executeFetchRequest(fetchRequest) | |
} catch { | |
//handle errors | |
print (error) | |
return nil | |
} | |
//defaultCenter.postNotificationName(AppDataEvents.DataFoundLocal, object: nil) | |
return results | |
} | |
/* Finds an array of entity in the MOC if any exists | |
* | |
* Usage: | |
* eg. var items = CustomEntity.findInStore(dbStore) as? [CustomEntity] | |
*/ | |
class func findInStore(store: DataStore) -> [AnyObject]? { | |
return findInStore(store, sortDescriptors: nil, predicate: nil) | |
} | |
/* Finds an array of entity in the MOC if any exists using an optional | |
* predicate. | |
* | |
* Usage: | |
* eg. var items = CustomEntity.findInStore(dbStore, predicate: | |
* NSPredicate(format: "attribute = %@", someValue)) as? [CustomEntity] | |
*/ | |
class func findInStore(store: DataStore, predicate: NSPredicate?) -> [AnyObject]? { | |
return findInStore(store, sortDescriptors:nil, predicate:predicate) | |
} | |
/* Finds an array of entity in the MOC if any exists using an optional | |
* predicate. | |
* | |
* Replaces: | |
* let predicate = NSPredicate(format:format, argumentArray:arguments) | |
* | |
* Usage: | |
* eg. var items = CustomEntity.findInStore(dbStore, predicate: | |
* NSPredicate(format: "%@ = %@", arguments)) as? [CustomEntity] | |
*/ | |
class func findInStore(store: DataStore, format: String, arguments: AnyObject ...) -> [AnyObject]? { | |
let predicate = NSPredicate(format:format, arguments) | |
return findInStore(store, sortDescriptors:nil, predicate:predicate) | |
} | |
/* Finds an array of entity in the MOC if any exists using an optional | |
* predicate and any number of variable arguments | |
* | |
* Usage: | |
* eg. var items = CustomEntity.findInStore(dbStore, predicate: | |
* NSPredicate(format: "(attributeName IN %@)", | |
* arguments: "value1","value2","value3",...)) as? | |
* [CustomEntity] | |
* | |
* Replaces: | |
* let predicate = NSPredicate(format:format, argumentArray:arguments) | |
* | |
* More Info: | |
* http://www.cocoawithlove.com/2009/05/variable-argument-lists-in-cocoa.html | |
*/ | |
class func findInStore(store: DataStore, sortDescriptors:[NSSortDescriptor]?, format: String, arguments: CVaListPointer) -> [AnyObject]? { | |
let predicate = NSPredicate(format: format, arguments: arguments) | |
return findInStore(store, sortDescriptors:sortDescriptors, predicate:predicate) | |
} | |
/* Finds an array of entity in the MOC if any exists using an optional | |
* predicate with an array of arguments | |
* | |
* Usage: | |
* eg. var items = CustomEntity.findInStore(dbStore, predicate: | |
* NSPredicate(format: "(%K != %@ AND %K = %@)", argumentArray:["key1","value1","key2","value2"])) | |
* as? [CustomEntity] | |
*/ | |
class func findInStore(store: DataStore, format: String, argumentArray: [AnyObject]?) -> [AnyObject]? { | |
let predicate = NSPredicate(format: format, argumentArray: argumentArray) | |
return findInStore(store, sortDescriptors:nil, predicate:predicate) | |
} | |
class func findOneInStore(store: DataStore, format: String, arguments: AnyObject ...) -> AnyObject? { | |
let results = self.findInStore(store, format: format, arguments: arguments) | |
if (results != nil && results?.count > 0) { | |
return results?[0] | |
} | |
else { | |
return nil | |
} | |
} | |
func removeFromStore() { | |
self.managedObjectContext!.deleteObject(self); | |
} | |
class func removeFromStore(store: DataStore) { | |
if let items:[AnyObject]? = self.findInStore(store) { | |
for item in items! { | |
store.context!.deleteObject(item as! NSManagedObject) | |
} | |
} | |
} | |
} | |
@objc class DataStore:NSObject { | |
final var modelName: String = "" | |
final var persistentStoreCoordinator: NSPersistentStoreCoordinator? = nil | |
init(modelName: String) { | |
self.modelName = modelName | |
} | |
func initPersistentStore() { | |
persistentStoreCoordinator = nil | |
} | |
// | |
// Send back the managedObjectContext for more detailed operations. | |
// | |
var context: NSManagedObjectContext? { | |
get { | |
return managedObjectContext | |
} | |
} | |
lazy var applicationDocumentsDirectory: NSURL = { | |
let urls = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask) | |
return urls[urls.count-1] as NSURL | |
}() | |
lazy var managedObjectModel: NSManagedObjectModel = { | |
let modelURL = NSBundle.mainBundle().URLForResource(self.modelName, withExtension: "momd")! | |
//let modelURL = NSBundle.mainBundle().URLForResource(self.modelName, withExtension: "momd")! | |
var model = NSManagedObjectModel(contentsOfURL: modelURL) | |
if (model != nil) { | |
return model! | |
} | |
return NSManagedObjectModel() | |
// return appDelegate.managedObjectModel | |
}() | |
lazy var managedObjectContext: NSManagedObjectContext? = { | |
self.initPersistentStore() | |
let coordinator = self.persistentStoreCoordinator | |
if coordinator == nil { | |
return nil | |
} | |
var managedObjectContext = NSManagedObjectContext() | |
managedObjectContext.persistentStoreCoordinator = coordinator | |
return managedObjectContext | |
}() | |
func save () { | |
if managedObjectContext!.hasChanges { | |
do { | |
try managedObjectContext!.save() | |
} catch { | |
// Replace this implementation with code to handle the error appropriately. | |
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. | |
let nserror = error as NSError | |
print("Unresolved error \(nserror), \(nserror.userInfo)") | |
//abort() | |
} | |
} else { | |
defaultCenter.postNotificationName(AppDataEvents.DataSaved, object: nil) | |
} | |
// if let moc = self.managedObjectContext { | |
// var error: NSError? = nil | |
// if moc.hasChanges && !moc.save(&error) { | |
// // Replace this implementation with code to handle the error appropriately. | |
// // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. | |
// //println("Unresolved error \(error), \(error!.userInfo)") | |
// //abort() | |
// } else { | |
// defaultCenter.postNotificationName(AppDataEvents.DataSaved, object: nil) | |
// } | |
// | |
// } | |
// } | |
} | |
@objc class MemoryDataStore: DataStore { | |
override init(modelName:String) { | |
super.init(modelName: modelName) | |
} | |
override func initPersistentStore() { | |
let coordinator: NSPersistentStoreCoordinator? = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel) | |
//let error: NSError? = nil | |
//let failureReason = "There was an error creating or loading the application's saved data." | |
do { | |
try coordinator!.addPersistentStoreWithType(NSInMemoryStoreType, configuration: nil, URL: nil, options: nil) | |
} catch { | |
let dict = NSMutableDictionary() | |
dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data" | |
//dict[NSLocalizedFailureReasonErrorKey] = failureReason | |
dict[NSUnderlyingErrorKey] = error as NSError | |
//internalError = NSError(domain: self.modelName, code: 9999, userInfo: dict as [NSObject : AnyObject]!) | |
} | |
persistentStoreCoordinator = coordinator; | |
// Replace this with code to handle the error appropriately. | |
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. | |
//println("Unresolved error \(error), \(error!.userInfo)") | |
//abort() | |
} | |
} | |
} | |
@objc class DBDataStore: DataStore { | |
final var databaseName: String = "" | |
@objc | |
init(modelName: String, databaseName: String) { | |
super.init(modelName: modelName) | |
self.databaseName = databaseName | |
} | |
override func initPersistentStore() { | |
let coordinator: NSPersistentStoreCoordinator? = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel) | |
let url = self.applicationDocumentsDirectory.URLByAppendingPathComponent(self.databaseName + ".sqlite") | |
// var error: NSError? = nil | |
// var failureReason = "There was an error creating or loading the application's saved data." | |
// | |
// Setup automatic migrations | |
// | |
let options = [ | |
NSMigratePersistentStoresAutomaticallyOption: true, | |
NSInferMappingModelAutomaticallyOption : true | |
] | |
do { | |
try coordinator!.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: options) | |
} catch { | |
// Report any error we got. | |
var dict = [String: AnyObject]() | |
dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data" | |
//dict[NSLocalizedFailureReasonErrorKey] = failureReason | |
dict[NSUnderlyingErrorKey] = error as NSError | |
let wrappedError = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict) | |
// Replace this with code to handle the error appropriately. | |
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. | |
NSLog("Unresolved error \(wrappedError), \(wrappedError.userInfo)") | |
abort() | |
} | |
} | |
} | |
//allocate the dbStore | |
let dbStore = DBDataStore(modelName: "ths", databaseName: "ths") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment