|
1 |
| -### [Managing Records With Fetched Results Controllers](https://cocoacasts.com/managing-records-with-fetched-results-controllers/) |
| 1 | +### [Exploring the Fetched Results Controller Delegate Protocol](https://cocoacasts.com/exploring-the-fetched-results-controller-delegate-protocol/) |
2 | 2 |
|
3 | 3 | #### Author: Bart Jacobs
|
4 | 4 |
|
5 |
| -The `NSFetchedResultsController` class isn't an essential component of a Core Data application, but it makes working with collections of managed objects much easier. This tutorial introduces you to the, almost magical, `NSFetchedResultsController` class. |
| 5 | +The `NSFetchedResultsController` class is pretty nice, but you probably aren't convinced yet by what you learned in the [previous tutorial](https://cocoacasts.com/managing-records-with-fetched-results-controllers/). In this tutorial, we explore the `NSFetchedResultsControllerDelegate` protocol. This protocol enables us to respond to changes in the managed object context the fetched results controller monitors. Let me show you what that means and how it works. |
6 | 6 |
|
7 |
| -## What Is It? |
| 7 | +## Where We Left Off |
8 | 8 |
|
9 |
| -An application powered by Core Data needs to make sure the state of the persistent store is reflected by the user interface and vice versa. If a record is deleted from the persistent store, the user interface needs to be updated, informing the user about this event. |
| 9 | +In the [previous tutorial](https://cocoacasts.com/managing-records-with-fetched-results-controllers/), we ran into a problem I promised we'd solve in this tutorial. Whenever the user adds a new note, the table view isn't updated with the new note. Visit [GitHub](https://github.com/bartjacobs/ManagingRecordsWithFetchedResultsControllers) to clone or download the project we created in the [previous tutorial](https://cocoacasts.com/managing-records-with-fetched-results-controllers/) and open it in Xcode. |
10 | 10 |
|
11 |
| -The boilerplate code required to update a table view is pretty lengthy. For every table view that manages a list of records, you need to write the same boilerplate code. By using the `NSFetchedResultsController` class, you only need to write code that is specific to your application. Trivial tasks, such as updating a table view cell when a record is modified, are handled by the fetched results controller. |
| 11 | +```bash |
| 12 | +git clone https://github.com/bartjacobs/ManagingRecordsWithFetchedResultsControllers |
| 13 | +``` |
12 | 14 |
|
13 |
| -A fetched results controller manages the results of a fetch request. It notifies its delegate about any changes that affect the results of that fetch request. It even offers the ability to use an in-memory cache to improve performance. |
| 15 | +## Monitoring a Managed Object Context |
14 | 16 |
|
15 |
| -Even though the `NSFetchedResultsController` class was designed with table views in mind, it also works great with collection views. In this tutorial, we build a basic notes application that keeps track of your notes. We first need to create a project, set up the Core Data stack, and design the data model. |
| 17 | +Previously, I wrote that a fetched results controller monitors the managed object context it keeps a reference to. It does this to update the results of its fetch request. But how does it monitor the managed object context? How does the fetched results controller know when a record is added, updated, or deleted? |
16 | 18 |
|
17 |
| -**Read this article on [Cocoacasts](https://cocoacasts.com/managing-records-with-fetched-results-controllers/)**. |
| 19 | +A managed object context broadcasts notifications for three types of events: |
| 20 | + |
| 21 | +- when one of its managed objects changes |
| 22 | +- when the managed object context is about to save its changes |
| 23 | +- when the managed object context has successfully saved its changes |
| 24 | + |
| 25 | +If an object would like to be notified of these events, they can add themselves as observers for the following notifications: |
| 26 | + |
| 27 | +- `NSNotification.Name.NSManagedObjectContextObjectsDidChange` |
| 28 | +- `NSNotification.Name.NSManagedObjectContextWillSave` |
| 29 | +- `NSNotification.Name.NSManagedObjectContextDidSave` |
| 30 | + |
| 31 | +With this in mind, the `NSFetchedResultsController` class is starting to lose some of its magic. A fetched results controller inspects the fetch request it was initialized with and it adds itself as an observer for `NSNotification.Name.NSManagedObjectContextObjectsDidChange` notifications. This gives the fetched results controller enough information to keep the collection of managed objects it manages updated and synchronized with the state of the managed object context it observes. |
| 32 | + |
| 33 | +You probably know that a notification has a name and, optionally, a `userInfo` dictionary. Each of the notifications I listed earlier has a `userInfo` dictionary that contains three key-value pairs. The dictionary includes which managed objects have been: |
| 34 | + |
| 35 | +- **inserted** |
| 36 | +- **updated** |
| 37 | +- **deleted** |
| 38 | + |
| 39 | +That is how the fetched results controller updates its collection of managed objects. The last piece of the puzzle is the `NSFetchedResultsControllerDelegate` protocol. The object that manages the fetched results controller, a view controller, for example, doesn't need to inspect the collection of managed objects the fetched results controller manages. It only needs to set itself as the delegate of the fetched results controller. |
| 40 | + |
| 41 | +Let's now take a closer look at the `NSFetchedResultsControllerDelegate` protocol. The methods of the protocol are: |
| 42 | + |
| 43 | +```swift |
| 44 | +optional public func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) |
| 45 | +optional public func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange sectionInfo: NSFetchedResultsSectionInfo, atSectionIndex sectionIndex: Int, for type: NSFetchedResultsChangeType) |
| 46 | + |
| 47 | +optional public func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) |
| 48 | +optional public func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) |
| 49 | + |
| 50 | +optional public func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, sectionIndexTitleForSectionName sectionName: String) -> String? |
| 51 | +``` |
| 52 | + |
| 53 | +The delegate method we are most interested in for this discussion is the first one, `controller(_:didChange:at:for:newIndexPath:)`. This method is invoked every time a managed object is inserted, updated, or deleted. How can we use this method for the **Notes** application? |
| 54 | + |
| 55 | +**Read this article on [Cocoacasts](https://cocoacasts.com/exploring-the-fetched-results-controller-delegate-protocol/)**. |
0 commit comments