3

I can create a case-insensitive string sort descriptor like this:

let titleSort = NSSortDescriptor(key: "title", ascending: true,
                                     selector: #selector(NSString.localizedCaseInsensitiveCompare))

I can't seem to figure out how to do it using the comparator signature:

class NSSortDescriptor {
  init(key: String?, ascending: Bool, comparator cmptr: @escaping Foundation.Comparator)
  ...
}

Do I have to create a new comparator from scratch or does something already exist for String?

TIA

RobertJoseph
  • 7,968
  • 12
  • 68
  • 113

2 Answers2

5

There isn't a global function for this as Comparator is meant to perform comparisons that aren't built-in. It's super flexible as it'd allow you to compare 2 different types of objects and define exactly how YOU want them to sort. In a very simple demonstration of how you might sort these, I created an example where I first check to see if both objects passed in are String, and if not I just treat them as though they should be ordered at the same level. Otherwise I sort them alphabetically (case insensitive, since I turn them to lowercase). Obviously you can make this as complex as you need based on what you anticipate needing to sort:

let descriptor = NSSortDescriptor(key: "title", ascending: true) { (string1, string2) -> ComparisonResult in
        guard let s1 = string1 as? String, let s2 = string2 as? String else {
            return ComparisonResult.orderedSame
        }
        if s1.lowercased() < s2.lowercased() {
            return ComparisonResult.orderedAscending
        } else if s1.lowercased() == s2.lowercased() {
            return ComparisonResult.orderedSame
        } else {
            return ComparisonResult.orderedDescending
        }
    }
creeperspeak
  • 5,403
  • 1
  • 17
  • 38
4

Example:

class C : NSObject {
    var id = 0
}

let desc = NSSortDescriptor(key: "id", ascending: true) { // comparator function
    id1, id2 in
    if (id1 as! Int) < (id2 as! Int) { return .orderedAscending }
    if (id1 as! Int) > (id2 as! Int) { return .orderedDescending }
    return .orderedSame
}

// test:

let c1 = C(); let c2 = C(); let c3 = C()
c1.id = 100; c2.id = 50; c3.id = 25
let arr = [c1,c2,c3]
let arr2 = (arr as NSArray).sortedArray(using: [desc])
matt
  • 515,959
  • 87
  • 875
  • 1,141