1

I am at the stage of optimizing my core data code,

I am making a messaging app, and I only want to load 50 messages at a time. However, looking at the timeprofile Data below, the fetchrequest loads all the messages at once. Afterwards, it loads all the messages in batches of 50 without even scrolling. So it's like not even doing anything.

Any help would be greatly appreciated.

lazy var fetchedResultsControler: NSFetchedResultsController = {
    let fetchRequest = NSFetchRequest(entityName: "Mesages")
    fetchRequest.fetchBatchSize = 20
    fetchRequest.sortDescriptors = [NSSortDescriptor(key: "timestamp", ascending: true)]
    fetchRequest.predicate = NSPredicate(format: "user.id = %@", self.friend!.id!)
    let moc = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
    let frc = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: moc, sectionNameKeyPath: nil, cacheName: nil)
    frc.delegate = self
    return frc
}()

 override func viewDidLoad() {
    super.viewDidLoad()

    do {
        try fetchedResultsControler.performFetch()


    } catch let err {
        print(err)
    }

    self.fetchData = fetchedResultsControler.fetchedObjects as! [Mesages]}

This is the CoreData time profiling data:

enter image description here

slimboy
  • 1,633
  • 2
  • 22
  • 45

1 Answers1

2

That's correct behavior, per the NSFetchRequest documentation:

When the fetch is executed, the entire request is evaluated and the identities of all matching objects recorded, but no more than batchSize objects’ data will be fetched from the persistent store at a time. The array returned from executing the request will be a proxy object that transparently faults batches on demand. (In database terms, this is an in-memory cursor.

If, instead, you want explicit control of the fetch grouping, use a combination of fetchLimit and fetchBatchSize instead. But at that point you're fighting the features of NSFetchedResultsController.

What are you really trying to do with the fetchData array?

Hal Mueller
  • 7,019
  • 2
  • 24
  • 42
  • `for object in fetchData { if object.isSender == true { self.JSQmessages.append(JSQCell(senderId: "danzo", senderDisplayName: "incoming", date: object.timestamp,text: object.text)) }` – slimboy Aug 15 '16 at 21:41
  • I'm using the code above to append the messages to my JSQcell which populates all of my table with the messages. my app freezes whenever it loads the controller because of the many messages that are loading. Do you know of any ways to optimize this behaviour? Thank you so much for the help, I really need it right now! – slimboy Aug 15 '16 at 21:43
  • 1
    You're fighting the framework. I assume JSQCell is a subclass of UITableviewCell? Instead of fetching the entire array and creating a complete array of tableview cells, use `tableView:cellForRowAtIndexPath:` to populate the cells as they're presented on screen. NSFetchedResultsController is specifically written to make this easy. Start here: https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/CoreData/nsfetchedresultscontroller.html – Hal Mueller Aug 15 '16 at 21:55