vp5
vp5

Reputation: 438

Setting NSDate to an NSManagedObject slow?

I am currently developing a Core Data application. I have a table view that shows a list of items whose attribute scheduled (which is a date) is nil and a BOOL attribute is NO. There is a button in each of the table view cells that allows the user to set the date in a modal view. There is a date picker in the modal view. The item is passed to that modal view controller.

The date is set when the user taps the Done button in the modal view. The date is set with this line of code:

self.item.scheduled = self.datePicker.date;

Apparently this line of code causes the UI to be blocked for ~1 second (on a 5th generation iPod touch), which is undesired behavior. I used Instruments and discovered that -[NSManagedObjectContext(_NSInternalChangeProcessing) _processRecentChanges:] took over 900.0ms.

Can someone please enlighten me as to what is causing the slowness? I am using just one MOC at the moment. Am I supposed to use another to make the change?

Edit: The method that took the longest time I got from Instruments tells me that the table view controller seems to have tried to re-fetch or update the cell, causing the slowness. I have -com.apple.CoreData.SQLDebug 1 passed on launch though, but no message was shown when the date was set.

This is the call tree I got from Instruments.

Call tree

CoreDataTableViewController is taken from a book about Core Data that I read. It is mostly the same as the one found here.

Upvotes: 2

Views: 142

Answers (1)

vp5
vp5

Reputation: 438

I finally found the answer. It turns out Auto Layout is extremely slow when offscreen. This is why it can be seen in the call tree that the layout operation took the majority of time.

The solution I chose was to remove the table view controller as the NSFetchedResultsController's delegate in viewWillDisappear:. Then, in viewWillAppear:, I perform a re-fetch and call reloadData on the table view, and set the NSFetchedResultsController's delegate property back to self (which is the table view controller).

EDIT: As amb mentioned in the comments, the solution above is a bad approach. This is the better approach. I should add that my table view only correctly reloaded when I added

if(self.tableView.window == nil)
    return;

also to controllerWillChangeContent:.

Upvotes: 2

Related Questions