Stack

A Type-Safe, Thread-Safe-ish approach to CoreData in Swift

48
0
Swift
Stack Logo

Stack

CI Status
Version
Language
Platform

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)

Introducing Stack

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:

  • Type-safe inserts, updates and deletes
  • Query chaining
  • Custom Query class for setting up sorting, filtering, etc…
  • Transaction based API – No access to contexts!
  • Asynchronous
  • Lightweight – Swift function overloads allow the API to remain clean and concise
  • NSFetchedResultsController support – convenience init()
  • See Documentation for more…

Goal

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 😃

Need to Know

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 😉

Docs

To learn more about how to use Stack. Checkout the included example project, read over the unit tests or checkout the documentation.

Usage

To run the example project, clone the repo, and run pod install from the Example directory first.

Installation

Stack is available through CocoaPods. To install
it, simply add the following line to your Podfile:

pod “Stack”

Author

Shaps, [email protected]

License

Stack is available under the MIT license. See the LICENSE file for more info.

Attribution

  • All code is my own, no 3rd party code is used in this project at all.