Created
August 21, 2014 03:10
-
-
Save jparishy/01dd7923dda41ad641d5 to your computer and use it in GitHub Desktop.
Core Data in Swift
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
// | |
// main.swift | |
// SwiftData | |
// | |
// Created by Julius Parishy on 8/20/14. | |
// Copyright (c) 2014 le. All rights reserved. | |
// | |
import Foundation | |
import CoreData | |
class Stack { | |
let modelURL: NSURL | |
let storeURL: NSURL? | |
let storeType: String? | |
let storeOptions: NSDictionary? | |
init(modelURL: NSURL, storeURL: NSURL?, storeType: String?, storeOptions: NSDictionary?) { | |
self.modelURL = modelURL | |
self.storeURL = storeURL | |
self.storeType = storeType | |
self.storeOptions = storeOptions | |
} | |
convenience init(modelURL: NSURL, storeURL: NSURL?) { | |
self.init(modelURL: modelURL, storeURL: storeURL, storeType: NSSQLiteStoreType, storeOptions: nil) | |
} | |
lazy var persistentStoreCoordinator : NSPersistentStoreCoordinator? = { | |
return Stack._persistentStoreCoordinator(self.modelURL, storeURL: self.storeURL, storeType: self.storeType, storeOptions: self.storeOptions) | |
}() | |
lazy var backgroundQueueContext : Context? = { | |
if let masterManagedObjectContext = Stack._managedObjectContextWithConcurrencyType(self, concurrencyType: .PrivateQueueConcurrencyType) { | |
masterManagedObjectContext.persistentStoreCoordinator = self.persistentStoreCoordinator | |
return Context(stack: self, masterManagedObjectContext: masterManagedObjectContext) | |
} else { | |
return nil | |
} | |
}() | |
lazy var mainQueueContext : Context? = { | |
if let masterManagedObjectContext = Stack._managedObjectContextWithConcurrencyType(self, concurrencyType: .MainQueueConcurrencyType) { | |
if let background = self.backgroundQueueContext { | |
masterManagedObjectContext.parentContext = background.masterManagedObjectContext | |
return Context(stack: self, masterManagedObjectContext: masterManagedObjectContext) | |
} else { | |
return nil | |
} | |
} else { | |
return nil | |
} | |
}() | |
private class func _managedObjectContextWithConcurrencyType(stack: Stack, concurrencyType: NSManagedObjectContextConcurrencyType) -> NSManagedObjectContext? { | |
if let coordinator = stack.persistentStoreCoordinator { | |
let masterManagedObjectContext = NSManagedObjectContext(concurrencyType: concurrencyType) | |
masterManagedObjectContext.undoManager = nil | |
return masterManagedObjectContext | |
} else { | |
return nil | |
} | |
} | |
private class func _persistentStoreCoordinator(modelURL: NSURL, storeURL: NSURL?, storeType: String?, storeOptions: NSDictionary?) -> NSPersistentStoreCoordinator? { | |
let model = NSManagedObjectModel(contentsOfURL: modelURL) | |
let coordinator = NSPersistentStoreCoordinator(managedObjectModel: model) | |
var error: NSError? | |
if !coordinator.addPersistentStoreWithType(storeType, configuration: nil, URL: storeURL, options: storeOptions, error: &error) { | |
return nil | |
} | |
return coordinator | |
} | |
} | |
class Transaction { | |
let context: Context | |
let managedObjectContext: NSManagedObjectContext | |
private init(context: Context) { | |
self.context = context | |
self.managedObjectContext = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType) | |
self.managedObjectContext.parentContext = self.context.masterManagedObjectContext | |
} | |
func executeQuery<T : AnyObject>(query: Query) -> Array<T>? { | |
let fetchRequest = NSFetchRequest(entityName: query.entityName) | |
fetchRequest.predicate = query.predicate | |
fetchRequest.sortDescriptors = query.sortDescriptors | |
var error: NSError? | |
if let results = self.managedObjectContext.executeFetchRequest(fetchRequest, error: &error) { | |
return results as? Array<T> | |
} else { | |
return nil | |
} | |
} | |
class func begin(context: Context, work: (Transaction) -> (Bool), success: (() -> ())?, failure: ((NSError) -> ())?) { | |
let transaction: Transaction = Transaction(context: context) | |
if work(transaction) { | |
var error: NSError? | |
if !transaction.managedObjectContext.save(&error) { | |
if let f = failure { | |
f(error!) | |
} | |
} else { | |
if let s = success { | |
s() | |
} | |
} | |
} | |
} | |
} | |
class Context { | |
let stack: Stack | |
internal let masterManagedObjectContext: NSManagedObjectContext | |
internal init(stack: Stack, masterManagedObjectContext: NSManagedObjectContext) { | |
self.stack = stack | |
self.masterManagedObjectContext = masterManagedObjectContext | |
} | |
internal convenience init(stack: Stack) { | |
let masterManagedObjectContext = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType) | |
masterManagedObjectContext.persistentStoreCoordinator = stack.persistentStoreCoordinator | |
self.init(stack: stack, masterManagedObjectContext: masterManagedObjectContext) | |
} | |
} | |
class Query { | |
private var sortDescriptors = [NSSortDescriptor]() | |
let entityName: String | |
let clauses: Dictionary<String, AnyObject> | |
init(entityName: String, clauses: Dictionary<String, AnyObject>) { | |
self.entityName = entityName | |
self.clauses = clauses | |
} | |
var predicate : NSPredicate? { | |
if clauses.count == 0 { | |
return nil | |
} | |
var string = "" | |
var index = 0 | |
for (key, value) in clauses { | |
string += "\(key) == '\(value)'" | |
if index < clauses.count - 1 { | |
string += " && " | |
} | |
index++ | |
} | |
return NSPredicate(format: string) | |
} | |
func sort(descriptors: [NSSortDescriptor]) -> Query { | |
for descriptor in descriptors { | |
sortDescriptors.append(descriptor) | |
} | |
return self | |
} | |
} | |
class SwiftDataModel : NSManagedObject { | |
class func coreDataEntityName() -> String { | |
return NSStringFromClass(self) | |
} | |
class func query(clauses: Dictionary<String, AnyObject>) -> Query { | |
let entityName = self.coreDataEntityName() | |
return Query(entityName: entityName, clauses: clauses) | |
} | |
} | |
@objc(Note) class Note : SwiftDataModel { | |
@NSManaged var text : NSString! | |
} | |
var stack = Stack(modelURL: NSURL(string: "Example.momd"), storeURL: NSURL(string: "Example.sqlite"), storeType: NSInMemoryStoreType, storeOptions: nil) | |
let context = stack.mainQueueContext | |
func doStuff() { | |
if let c = context { | |
Transaction.begin(c, work: { (transaction) in | |
var managedObjectContext = transaction.managedObjectContext | |
var entity = NSEntityDescription.entityForName(Note.coreDataEntityName(), inManagedObjectContext: managedObjectContext) | |
let texts = [ "Hello!", "Sup tho" ] | |
for text in texts { | |
var note : Note = NSManagedObject(entity: entity, insertIntoManagedObjectContext: managedObjectContext) as Note | |
note.text = text | |
} | |
return true | |
}, success: nil, failure: { (error) in | |
println("Failed :( \(error.localizedDescription)") | |
}) | |
Transaction.begin(c, work: { (transaction) in | |
let query = Note.query([:]).sort([ NSSortDescriptor(key: "text", ascending: false) ]) | |
if let results : Array<Note> = transaction.executeQuery(query) { | |
println("Results: \(results.map { (note) in note.text })") | |
} | |
return true | |
}, success: nil, failure: { (error) in | |
println("Query failed: \(error.localizedDescription)") | |
}) | |
} | |
} | |
doStuff() | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment