How to observe changes on single instance of NSManagedObject

Your Answer

Sign up or log in Sign up using Google Sign up using Facebook Sign up using Email and Password

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Video

What the world looks like today

Dirty-checking

Where have you seen data-binding before? Well, if you use a modern MV* library for building your webapps (e.g Angular, Knockout) you’re probably used to binding model data to the DOM. As a refresher, here’s an example of a Phone list app where we’re binding the value of each phone in a phones array (defined in JavaScript) to a list item so that our data and UI are always in sync:

and the JavaScript for the controller:

(Demo)

Anytime the underlying model data changes, our list in the DOM gets updated. How does Angular achieve this? Well, behind the scenes it’s doing something called dirty-checking.

The basic idea with dirty-checking is that anytime

The basic idea with dirty-checking is that anytime data could have changed, the library has to go and check if it did change via a digest or change cycle. In Angular’s case, a digest cycle identifies all expressions registered to be watched to see if there’s a change. It knows about a model’s previous values and if they have changed, a change event is fired. For a developer, the main benefit here is that you get to use raw JavaScript object data which is pleasant to use and composes fairly well. The downside is that it has bad algorithmic behavior and is potentially very expensive.

The expense of this operation is proportional to t

The expense of this operation is proportional to the total number of observed objects. I may need to do a lot of dirty checking. Also may need a way to trigger dirty-checking when data *might* have changed. There are lots of clever tricks frameworks use for this. It’s unclear if this is ever going to be perfect.

The web ecosystem should have more ability to innovate and evolve its own declarative mechanisms, e.g.

  • Constraint-based model systems
  • Auto-persistence systems (e.g persisting changes to IndexedDB or localStorage)
  • Container objects (Ember, Backbone)

Container objects are where a framework creates objects which on the inside hold the data. They have accessors to the data and they can capture what you set or get and internally broadcast. This works well. It’s relatively performant and has good algorithmic behavior. An example of container objects using Ember can be found below:

The expense of discovering what changed here is proportional to the number of things that changed. Another problem is now you’re using this different kind of object. Generally speaking you have to convert from data you’re getting from the server to these objects so they’re observable.

This doesn’t compose particularly well with existing JS code because most code assumes it can operate on raw data. Not for these these specialized kinds of objects.

Reporting on Observations

It is fairly easy to report on controlled observations – the quantative aspects can be condensed into graphs or tables. Qualitative analysis should be treated more cautiously and data compiled and used as a signpost to further research rather than being accepted as absolute truth.

Step Three: Give the Emotion a Form

Now that the emotion is out in front of you, close your eyes and answer the following questions: If your emotion had a size, what size would it be? If your emotion had a shape, what shape would it be? If your emotion had a color, what color would it be?

Once you’ve answered these questions, imagine the emotion out in front of you with the size, shape, and color you gave it. Just watch it for a few moments and recognize it for what it is. When you are ready, you can let the emotion return to its original place inside you.

Handling Notifications

It is up to the object observing the managed object context to decide what to do with the information it receives. Let me first show you what that information looks like.

The object property of the notification is the managed object context posting the notification. If an object is observing multiple managed object contexts, you can inspect the object property to find out which managed object context posted the notification.

The information we are interested in is stored in the userInfo dictionary of the notification object. The userInfo dictionary includes three important keys:

  • NSInsertedObjectsKey
  • NSUpdatedObjectsKey
  • NSDeletedObjectsKey

The value of each of these keys corresponds with a set of managed objects. These sets contain the managed objects that were inserted into, updated, and deleted from the managed object context that posted the notification.

As I mentioned earlier, it is up to the observer to decide what to do with the information included in the notification. It is important to emphasize that some notifications can be sent very frequently. The NSManagedObjectContextObjectsDidChangeNotification notification, for example, is sent every time a managed object is modified.

The frequency with which NSManagedObjectContextWillSaveNotification and NSManagedObjectContextDidSaveNotification notifications are posted depends on the application's Core Data implementation. Most of the Core Data applications I write, perform a save operation when the application enters the background or when it is about to be terminated. I explain this in more detail in Building the Perfect Core Data Stack.

Top Articles

Step One: Identify the Emotion

The first step is to identify the emotion you are having. If you are having more than one emotion, just pick one (you can go back and do this exercise with the other emotions later if you want to).

If you are having trouble identifying the emotion, sit for a moment and pay attention to your physical sensations and thoughts. See if you can give an emotion you are having a name (e.g., sadness, anger, shame).

Once you have a name for the emotion, write it down on a slip of paper.

Things You Can Do Online to People-Watch

Ever take the time to visit other people's pages not as a commenter, contributor, or something else, but simply as an observer? When you do this, you can enjoy the person's body of work much more, because you are allowing your mind to view his or her content free of judgment and without an obligation to interact with it. When people-watching online you will need: an email address that doesn't reveal your full name, profiles that don't display who you are or others you know, possibly and a different computer to work from since many sites do track your ISP address. People watching online requires time and sometimes patience especially when some sites are very busy, tend to shut down, or are slow.

1. Visit chat-rooms and forums, but don't participate in the discussions.

2. View a certain individual's profiles and public messages on social media sites without commenting, liking, etc. However, some sites might have a program set up to alert the person that you viewed his or her page.

3. Go to Google images and YouTube videos and you can view as many images as you like related to the individual without every talking to he or she in person.

4. You can catch live video of people on sites like Justin TV and live talk radio like BlogTalk Radio or Talkshoe.

5. Stop by "How-to" sites, personal blog pages, and more. You will find many videos and pictures where you can learn some new things and never have to worry about someone calling on you to participate.

You are never alone in Internet world. When it's cold, rainy, snowy, or all of the above, just sit back in your favorite chair, grab a warm blanket, and view others online.

An Example

I have created a basic application to illustrate what you can do with the information a managed object context sends its observers. To follow along, clone or download the project from GitHub and open it in Xcode. Build the application to make sure everything is working.

Monitoring Updates

The example application has the ability to create notes and link them to the current user. A user can have many notes and a note is always associated with one user.

The method we are interested in is managedObjectContextObjectsDidChange(_:) in the ViewController class. The ViewController class observes the managed object context it has a reference to and every time a managed object is modified in the managed object context, the managedObjectContextObjectsDidChange(_:) method is invoked.

In this method, we inspect the userInfo dictionary of the notification object and print every managed object that is inserted into and deleted from the managed object context. For updates, we print the properties and values that were modified. The changedValues() method returns a dictionary that contains the names of the properties that were modified, including the old value of the property.

Run the application in the simulator, tap the Profile button in the top left, and modify the first name of the user. When you tap the Save button at the bottom, the managed object is updated and a notification is posted by the managed object context. This is what you should see in Xcode's console.

As you can see, the changedValues() method is very convenient for understanding which properties were modified.

Monitoring Inserts

Add a new note to the user by tapping the + button in the top right. Enter a title in the text field and some content in the text view. Tap the Save button to save the note.

You may be surprised by the output in the console. Even though we inserted a note into the managed object context, the NSManagedObjectContextObjectsDidChangeNotification notification also includes information about a managed object being updated.

Taking a closer look should clarify what is happening. The set of managed objects inserted into the managed object context contains the note we added. That is to be expected.

The set of updated managed objects includes the user record to which the note was added. By setting the user property of the new note to the current user, Core Data automatically added the note to the set of notes of the user. This is reflected in the output in the console.

Remember that we only print the properties that were updated. The output shows us that the notes property was updated. There are currently two notes associated with the user.

Changed Values

There is one more thing I would like to show you. Stop the application to start with a clean slate. Run the application one more time and tap the Profile button to modify the properties of the user. Change the first name to Han and tap the Save button. This is what you should see in the console.

Tap the Profile button again and change the last name to Solo. Tap the Save button to update the user record. The output should now look like this.

The changedValues() method returns a dictionary that includes every property of the user record that has been modified since the record was fetched or since the record was last saved. In other words, Core Data coalesces the changes for us.

This is not always what you want, though. Fortunately, Core Data also provides an API that only lists the properties that were modified since the last NSManagedObjectContextObjectsDidChangeNotification notification was posted, changedValuesForCurrentEvent().

Resources

With thanks to Rafael Weinstein, Jake Archibald, Eric Bidelman, Paul Kinlan and Vivian Cromwell for their input and reviews.

Tags