A Type-Safe, Thread-Safe-ish approach to CoreData in Swift
Wouldn’t it be great to have a type-safe CoreData Stack?
Reading
let stack = Stack.defaultStack()
let query = Query<Person>().sort(byKey: "name", direction: .Ascending).filter("name == %@", name)
let results = try! stack.fetch(query)
print(results.first?.name)
Writing
let stack = Stack.defaultStack()
stack.write({ (transaction) -> Void in
let person = try transaction.fetchOrInsert("name", identifier: name) as Person
person.age = 35
}, completion: nil)
CoreData is a powerful API, but its easily misused and misunderstood. Stack attempts to remove many of the issues associated with using CoreData in your applications.
Specifically, Stack adds both type-safety and thread-safety (ish) methods for dealing with queries and updates.
Additionally, Stack provides a much more expressive API through features like:
The aim of Stack is to provide a clean, expressive abstraction from CoreData. Giving you the flexibility and power of CoreData, without all the headache surrounding contexts and thread management.
With Swift, Stack now supports type-safe queries giving you more confidence when implementing CoreData in your applications.
Stack 2.0 provides read-only access through the Stack itself, moving all write methods into a transaction. This prevents you from making mistakes and attempting to update objects outside of a transaction.
Stack is used in various production apps, but I still consider it an ever changing concept so input is welcome 😃
Reading
Once you have a Stack, reading is easy. You just need to construct a query and then call one of the fetch
methods on your stack. Note: The optional is required since a fetch may return nil.
let stack = Stack.defaultStack()
let query= Query<Person>(key: "name", identifier: "Shaps")
let person = try! stack.fetch(query).first
print(person?.name)
Now we can update that same object. Note: Thanks to Swift closures, we can safely re-define the variable with the same name.
Writing
let stack = Stack.defaultStack()
stack.write({ (transaction) -> Void in
let person = transaction.copy(person)
person.age = 35
}, completion: nil)
As you can see, all write actions occur ONLY inside a transaction, which prevents many common mistakes when implementing CoreData.
You probably noticed that copy()
function? This is another nice feature provided by Stack. Basically it will copy the object(s) into the current transaction/context so you don’t try to modify an object on the wrong thread. And don’t worry, all changes will be propogated to your other threads automatically 😉
To learn more about how to use Stack. Checkout the included example project, read over the unit tests or checkout the documentation.
To run the example project, clone the repo, and run pod install
from the Example directory first.
Stack is available through CocoaPods. To install
it, simply add the following line to your Podfile:
pod “Stack”
Shaps, [email protected]
Stack is available under the MIT license. See the LICENSE file for more info.