Search code examples
swiftxcodetableview

How to sort a piece of data (CoreData) in the tableView cell alphabetically?


I am trying to make a simple "Contacts" app. Everything works fine but I could not find a way to write the piece of data from CoreData to the tableView by sorted alphabetically.

I want that the people save their phone numbers and their names in CoreData and after that, they will be added to the array as Person object. Also, I want to write the names to the tableView cell label. As you can understand, those names must be in alphabetic order.

I have created the app with MVC and created an empty array to keep users' phone numbers and names. The type of the array is Person.

//Like below.
// I hold the informations in this array.
var personList = [Person]()

//here is the cell format I am using in the app. 

   func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    
    let cell = tableView.dequeueReusableCell(withIdentifier: "tableViewCell", for: indexPath) as! TableViewCell
    let person =  personList[indexPath.row]
    cell.imageBackground.tintColor = cell.backgroundColors.randomElement()
    cell.imageLabel.text = String(person.personFirstLetter.first!)
    cell.nameLabel.text = person.personName
 
  
    
    return cell
}

 //this is how I get data from the user.

 @objc func getData() {
personList.removeAll(keepingCapacity: false)
    let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
    let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "People")
    fetchRequest.returnsObjectsAsFaults = false
    
    do {
     let results =  try context.fetch(fetchRequest)
        for result in results as! [NSManagedObject]{
            if let name = result.value(forKey: "name") as? String{
                if let phoneNumber = result.value(forKey: "number") as? String{
                    if let firstLetter = result.value(forKey: "letter") as? String{
                        personList.append(Person(personName: name, personNumber: phoneNumber, personFirstLetter: firstLetter))
                        
                    }
                }
            }
        }
        
    } catch  {
        print(error.localizedDescription)
    }

I don't actually know what to share here and how or where to adopt the alphabetic sorting.

Thanks for all. Cheers!


Solution

  • The most efficient way is to sort the records while fetching them. And use the real type in the request rather than unspecified NSFetchRequestResult

    let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
    let fetchRequest = NSFetchRequest<People>(entityName: "People")
    fetchRequest.sortDescriptors = [NSSortDecriptor(key: "name", ascending: true)]
    

    Further don't map the objects to another type, use the People class, declare the datasource array

    var personList = [People]()
    

    and this is the entire code to fetch the data, only one line

    do {
       personList = try context.fetch(fetchRequest)
    } catch  {
       print(error.localizedDescription)
    }
    

    The changes in cellForRow are quite subtle.

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        let cell = tableView.dequeueReusableCell(withIdentifier: "tableViewCell", for: indexPath) as! TableViewCell
        let person = personList[indexPath.row]
        cell.imageBackground.tintColor = cell.backgroundColors.randomElement()
        cell.imageLabel.text = String(person.letter.first!)
        cell.nameLabel.text = person.name
        
        return cell
    }