Search code examples
iosuitableviewnsstringnsfetchedresultscontroller

Minimum letter for string sorting


Question: I have Strings: "A", "C", "D", "1", "И" (Russian), "你" (Chinese). And I have string let alwaysFirstString = "?" I want alwaysFirstString to be always first when I use general iOS sorting. What should be the alwaysFirstString instead of "?" ?

Why I need that:

In my application I display contacts like in Telegram application:

  • At first I need to display contacts that have their own contacts in my application (server returns me these contacts)
  • After that I display other contacts (grouped by the first letter in their surname)

I display contacts in group UITableView. So in my DBContact object in core data I have sectionInfo field. Usually this field = A, B, C, F (The first letter of surname), but for some contacts (I want them to be always first) I need to have other symbol. So this symbol should always be the first when I use regular sortDesctriptors in FetchResultController (better for all languages).

Here is the code:

let entityName = kDBContact
let fetchRequest = NSFetchRequest<DBContact>(entityName: entityName)
//            let entityDescription = NSEntityDescription.entity(forEntityName: entityName, in: DatabaseManager.sharedInstance.managedObjectContext)
//            fetchRequest.entity = entityDescription
fetchRequest.fetchBatchSize = 20
// sort
fetchRequest.sortDescriptors = [NSSortDescriptor(key: "sectionInfo", ascending: true), NSSortDescriptor(key: "nameAndSurname", ascending: true)]
// sometimes we have predicate when user tries to search smth
var predicate: NSPredicate?
var formatForPredicate = ""
// filter not to show fake contacts
formatForPredicate += "(isFakeContact == false)"
var argumentArray = [AnyObject]()
// text filter in search bar
if help_needToShowFilteredContacts() {
    if formatForPredicate.length > 0 {
       formatForPredicate += " AND "
    }
    formatForPredicate += "((nameAndSurname CONTAINS[cd] %@) OR (phoneNumbers.numberOnlyDigits CONTAINS[cd] %@))"
    argumentArray.append(resultSearchController.searchBar.text! as AnyObject)
    argumentArray.append(resultSearchController.searchBar.text! as AnyObject)
}
sectionNameKeyPath = "sectionInfo"
// filter to show only favourites
if segmentedControl.selectedSegmentIndex == segmented_favouriteIndex {
    sectionNameKeyPath = nil

    if formatForPredicate.length > 0 {
       formatForPredicate += " AND "
    }
    formatForPredicate += "(isFavourite == true)"
}
if formatForPredicate.length > 0 {
   predicate = NSPredicate(format: formatForPredicate, argumentArray: argumentArray)
}
fetchRequest.predicate = predicate
self.fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest as! NSFetchRequest<NSFetchRequestResult>, managedObjectContext: DatabaseManager.sharedInstance.managedObjectContext, sectionNameKeyPath: sectionNameKeyPath, cacheName: nil)

So you can see fetchRequest.sortDescriptors = [NSSortDescriptor(key: "sectionInfo", ascending: true), NSSortDescriptor(key: "nameAndSurname", ascending: true)] . So in sectionInfo I have this First characters of the surname, and I want registered contacts (with special character in sectionInfo) to be always the 1st.


Solution

  • I used "" for maximum symbol and " " for minimum. Later in fetched result controller delegate I have:

    func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
            if let sections = fetchedResultsController?.sections {
                let currentSection = sections[section]
                let name = currentSection.name
                if "" == name {
                    return "#"
                }
                else if " " == name {
                    return "Registered contacts"
                }
                return name
            }
    
            return nil
        }
    

    I found last symbol here What character to use to put an item at the end of an alphabetic list?