Slee
Slee

Reputation: 28268

how can I see what methods are slowing the display of my UIViewController?

I have a very complex UIViewController that loads extremely slow sometimes, it can take 4 or 5 seconds.

I do use Core Data and I have -com.apple.CoreData.SQLDebug 1 set and have ruled out that it is the loading of my data. CoreData: annotation: total fetch execution time: 0.0166s for 314 rows.

I do have this data loaded into a UITableView but was under the impression only the first visible rows get renderend so no matter how many rows I have (< 500 currently) it should not slow the display of the UIView.

I looked at instruments and checked out Time Profiler but I did not see a way to tell which method in this UIView would be slow.

Any suggestions?

UPDATE:
For me this was caused by my custom row heights, those all have to get calculated FIRST before any data in shown:
heightForRowAtIndexPath being called for all rows & how many rows in a UITableView before performance issues?

Upvotes: 3

Views: 160

Answers (1)

David LaMacchia
David LaMacchia

Reputation: 36

I recently had a UITableViewController that was managing ~8000 rows via Core Data. The data was being managed with NSFetchedResultsController; I don't know if you're using NSFetchedResultsController with a NSFetchRequest but if you're presenting a table populated via Core Data, I highly recommend it.

That said, there's a lot of tweaking you can do when you're creating a NSFetchRequest to improve performance of your fetch and render, which is where I'd guess the performance bottleneck is. You can fetch batches of rows so that the initial render of your table is fast and additional fetches are performed as the user scrolls your table:

[fetchRequest setFetchBatchSize:25];

I recommend reading Apple's guide to performance tuning and Core Data:

https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CoreData/Articles/cdPerformance.html

Since you're using Instruments, also check out (per the above link) the Core Data cache misses, fetches, and saves. That might give you an indication of where the time is being spent.

You might also try setting breakpoints table methods such as cellForRowAtIndexPath: to see how many rows are being rendered when the view is loaded vs. when the user scrolls the table view.

I also set the following which seemed to improve performance in my situation:

[fetchRequest setShouldRefreshRefetchedObjects:YES];
[fetchRequest setReturnsObjectsAsFaults:NO];

Re: faults, here's what Apple's NSFetchedRequest documentation says:

The default value is YES. This setting is not used if the result type (see resultType) is NSManagedObjectIDResultType, as object IDs do not have property values. You can set returnsObjectsAsFaults to NO to gain a performance benefit if you know you will need to access the property values from the returned objects.

Core Data can be incredibly complex. If you're only going to use a single NSManagedObjectContext check out Erica' Sadun's "core data helper" from her excellent iPhone Developer's Cookbook. If you're going to be doing a lot with Core Data, I highly recommend MagicalRecord which can handle a lot of the heavy lifting of merging nested NSManagedObjectContexts, handling multiple threads, and more: https://github.com/magicalpanda/MagicalRecord

Hope this helps!

Upvotes: 2

Related Questions