0

I am using NSFetchResultController to show sections in my table. I got a NSDate attribute to sort by date. I am fetching the data correctly, my issue is that I want the sections to show the month of the year like July, August. Currently the dates are showing up like the image below. enter image description here

FetchRequest

var fetchResultController: NSFetchedResultsController = { () -> NSFetchedResultsController<Gratitude> in
    let fetchRequest = NSFetchRequest<Gratitude>(entityName: "Gratitude")
    let sortByDate = NSSortDescriptor(key: "date", ascending: false)
    fetchRequest.sortDescriptors = [sortByDate]
    let frc = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: Context.shared.persistentContainer.viewContext, sectionNameKeyPath: "date" , cacheName: nil)  
    return frc    
}()

Header

func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    //return g2[section].monthLabel.uppercased()
   let sectionInfo = fetchResultController.sections?[section]
    return sectionInfo?.name
}

numberOfRowsInSection

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

    if let count = fetchResultController.sections?[section].numberOfObjects{
        return count
    }

    return 0
}

numberOfSections

func numberOfSections(in tableView: UITableView) -> Int {
    if let sections = fetchResultController.sections?.count {
        return sections
    }
   return 0

}

Any help would be appreciated.

Updated Image

enter image description here

Iam Wayne
  • 561
  • 6
  • 26

2 Answers2

1

Okay, then I assume sectionInfo?.name is giving you that date string, which you have to convert to a date and get the month from. You can do it like this:

func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
  let sectionInfo = fetchResultController.sections?[section]
  return monthFrom(string: sectionInfo?.name)
}

//Make a function that converts any string with the format you showed above
//to the month for that string
func monthFrom(string: String?) -> String? {
  guard let dateString = string else { return nil }
  //Set up Date Formatter to create date object from the string
  let dateFormatter = DateFormatter()
  dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss +SSSS"
  //Verify string is a valid date
  guard let date = dateFormatter.date(from: dateString) else { return nil }
  //Pull month name from date
  dateFormatter.dateFormat = "MMMM"
  return dateFormatter.string(from: date)
}
Kayla Galway
  • 662
  • 4
  • 7
0

one thing missing here is a transient variable that returns only the month as string or a date component. sectionNameKeyPath this needs to be set to it, otherwise setting it to the date will have a sections created on the date which includes seconds, minutes, hrs, day and so one. So You really need to use some data that represent the year-month of the date and not the full month. I seen an example on the apple website.

https://developer.apple.com/library/archive/samplecode/DateSectionTitles/Introduction/Intro.html#//apple_ref/doc/uid/DTS40009939

Pascale Beaulac
  • 889
  • 10
  • 28