Search code examples
iosswiftcore-datansfetchedresultscontrollernsfetchrequest

NSFetchedResultsController with table like iMessage


I have Core Data database. Structure is on the image (DBContact have many DBMessages with property messages, each DBMessage have one contact with property contact):

enter image description here

I want to display messages grouped by contact and sorted by date. So the number of rows have to be = number of contacts with messages. And in each row I have to display avatar, nameAndSurname of contact and text and date of last message of this contact.

The only solution I found is:

    let entityName = kDBOrder
        let entityDescription = NSEntityDescription.entityForName(entityName, inManagedObjectContext: managedObjectContext)
        let fetchRequest = NSFetchRequest()
        fetchRequest.entity = entityDescription
        fetchRequest.fetchBatchSize = 20
        // sort
        fetchRequest.sortDescriptors = [NSSortDescriptor(key: "contact.id", ascending: false), NSSortDescriptor(key: "date", ascending: false)]
        let sectionNameKeyPath: String? = "contact.id"
        self.fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: managedObjectContext, sectionNameKeyPath: sectionNameKeyPath, cacheName: nil)
       fetchedResultsController!.delegate = self
       if tableViewMain != nil {
          do {
             try fetchedResultsController!.performFetch()
          } catch {
             print("An error occurred in fetchresultcontroller")
          }
          tableViewMain.reloadData()
       }

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        var count = 0
        if let sections = fetchedResultsController?.sections {
            let currentSection = sections[section]
            count = currentSection.numberOfObjects
            // in each section we must have only 1 row
            if count > 0 {
                count = 1
            }
        }
        return count
    }

But in this case contacts will be sorted by id, but I need to sort them by date of last message. But if I change sortDescriptors to fetchRequest.sortDescriptors = [NSSortDescriptor(key: "date", ascending: false), NSSortDescriptor(key: "contact.id", ascending: false)] to sort by date first, it will not display contacts properly. Do anybody have ideas how to implement this?


Solution

  • I'd probably change the model to make life easier and do a little more processing earlier. Basically if add another relationship, 1-to-1, between the 2 entities and each time a new message is added is update that relationship - so you always have a direct pointer to the most recent message.

    Once you've done that your FRC and your table load speed are trivial because you just use contacts in the fetch. New messages are also handled correctly because the relationship gets updated so the contact changes and the FRC will see it.