If we look at the data model file for this app, we see that the ToDo entity is very simple, containing what you would expect: a title , priority and a done flag. What is more interesting is that each todo has a mandatory relation with a meta data object, which is created upon insert.

override func awakeFromInsert() { super.awakeFromInsert() metaData = NSEntityDescription.insertNewObjectForEntityForName(ToDoMetaData.entityName, inManagedObjectContext: managedObjectContext) as ToDoMetaData }

Extracting meta data into a separate entity separates concerns and makes it easier if we would want to serialize todos to a web service in the future. In the app, the NSFetchedResultsController will actually be set up to fetch the meta data objects instead of the todos themselves. This will soon be explained why.

The first property of the meta data entity, internalOrder , is an integer which orders the todos within a section. It gets updated when the user reorders the list with drag 'n' drop.

The second property, sectionIdentifier , is a string used to divide the todos into sections. NSFetchedResultsController requires that the sections are sorted in the same order as the rows so they can be fetched in batches. Since the sorting attributes must be stored in the persistent store, that also means the sectionNameKeyPath must either be stored itself or derived from a stored property.

Every time a property affecting a todo's displayed section changes (such as priority or done status), the section identifier must be updated. In Objective-C we could accomplish this with property overrides or KVO but unfortunately neither of these techniques are easily available for managed objects in Swift (as of Xcode 6 beta 5). Instead we have to remember to manually trigger an update when doing drag 'n' drop or marking a todo as done.

public func updateSectionIdentifier() { sectionIdentifier = sectionForCurrentState().toRaw() } private func sectionForCurrentState() -> ToDoSection { if toDo.done.boolValue { return .Done } else if listConfiguration.listMode == ToDoListMode.Simple { return .ToDo } else { switch ToDoPriority.fromRaw(toDo.priority)! { case .Low: return .LowPriority case .Medium: return .MediumPriority case .High: return .HighPriority } } }

Another nuisance is that NSFetchedResultsController assumes all sections are semantically equal and therefor always sorts them in alphabetical order. We get around this by assigning the sectionNameKeyPath to a Swift enum value with a method for getting the actual display name. This way, we achieve arbitrary sorting of sections. If we wanted to make the order of the sections dynamic, we could instead of using an enum, generate an identifier string runtime.

enum ToDoSection: String { case ToDo = "10" case HighPriority = "11" case MediumPriority = "12" case LowPriority = "13" case Done = "20" func title() -> String { switch self { case ToDo: return "Left to do" case Done: return "Done" case HighPriority: return "High priority" case MediumPriority: return "Medium priority" case LowPriority: return "Low priority" } } }

At last we have the ToDoListConfiguration . This object stores in which display mode (simple/prioritized) the table view is in. This could as well have been stored in NSUserDefaults or just in memory using state restoration between app launches. But since it affects the section identifier of the meta data objects, I found it suitable to have it connected in the persistent store.

Setting up the NSFetchedResultsController

private lazy var toDosController: NSFetchedResultsController = { let fetchRequest = NSFetchRequest(entityName: ToDoMetaData.entityName) fetchRequest.relationshipKeyPathsForPrefetching = ["toDo"] fetchRequest.sortDescriptors = [NSSortDescriptor(key: "sectionIdentifier", ascending: true), NSSortDescriptor(key: "internalOrder", ascending: false)] let controller = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: self.managedObjectContext, sectionNameKeyPath: "sectionIdentifier", cacheName: nil) controller.performFetch(nil) controller.delegate = self return controller }()

As we setup the fetched results controller, there are a couple of things to note. First, the entity we fetch is ToDoMetaData and not ToDo itself. The reason is that this is where our sorting keys and sectionNameKeyPath are stored. The fetched results controller can be setup with key paths directing to a related entity, but it only keeps track of changes on its original fetched dataset.

Since the meta data object has a one to one relationship to the real ToDo object, we can easily extract the todo once we have the metadata. To make this perform better, we add "toDo" to the relationshipKeyPathsForPrefetching property of the fetch request. Else, CoreData would fire a fault to the persistent store for every single todo once they are displayed in the table view.

The fetched results controller delegate calls which notify of changes to sections and objects are forwarded to a separate FetchControllerDelegate class, which uses an implementation mostly like the example found in the developer library. It responds to the delegate calls by informing the table view.

Animating change of done-state and display mode

With the data model and fetched results controller set up, it is dead simple to produce data driven animations.

override func tableView(tableView: UITableView!, didSelectRowAtIndexPath indexPath: NSIndexPath!) { tableView.deselectRowAtIndexPath(indexPath, animated: true) let toDo = toDoListController.toDoAtIndexPath(indexPath) toDo.done = !toDo.done.boolValue toDo.metaData.updateSectionIdentifier() toDo.managedObjectContext.save(nil) }

As we change done status, the meta data object will assign a new section identifier which the fetched results controller picks up to notify that the todo has moved from one section to another.