Search code examples
cocoanstableviewnsarraycontrollernssortdescriptor

NSSortDescriptor for NSArrayController to sort alphabetically and by string length


I have an NSArrayController and I'm trying to sort it base on length of the string and also alphabetically. The NSArrayController contains a string with space like this " ".

Here is my code:

    NSSortDescriptor *nameSortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];
    NSSortDescriptor *lengthSorter = [NSSortDescriptor sortDescriptorWithKey:@"length" ascending:YES];
[self.nameAC.content setSortDescriptors:@[lengthSorter, nameSortDescriptor]];

But this is the result of the sort:

enter image description here What I need to s first the string " " and after aaa, bbb, cccc, ddd.

The output in console of NSArrayController (nameAC):

(lldb) po _nameAC
<NSArrayController: 0x6080001c05a0>[entity: Tags, number of selected objects: 1]

The output in console of the NSArrayController content is the following:

(lldb) po _nameAC [entity: Tags, number of selected objects: 1]

(lldb) po _nameAC.content
<__NSArrayM 0x60000004f600>(
<Tags: 0x6000000a7260> (entity: Tags; id: 0x140002b <x-coredata://B7756C1E-B9F2-4C57-A1FA-272478C4D6A6/Tags/p5> ; data: {
    category = "0x40000b <x-coredata://B7756C1E-B9F2-4C57-A1FA-272478C4D6A6/Categories/p1>";
    product = "<relationship fault: 0x60800002ba80 'product'>";
    name = bbb;
}),
<Tags: 0x6000000a7200> (entity: Tags; id: 0x100002b <x-coredata://B7756C1E-B9F2-4C57-A1FA-272478C4D6A6/Tags/p4> ; data: {
    category = "0x40000b <x-coredata://B7756C1E-B9F2-4C57-A1FA-272478C4D6A6/Categories/p1>";
    product = "<relationship fault: 0x60800002a160 'product'>";
    name = aaa;
}),
<Tags: 0x6000000a7740> (entity: Tags; id: 0x1c0002b <x-coredata://B7756C1E-B9F2-4C57-A1FA-272478C4D6A6/Tags/p7> ; data: {
    category = "0x40000b <x-coredata://B7756C1E-B9F2-4C57-A1FA-272478C4D6A6/Categories/p1>";
    product = "<relationship fault: 0x60800002b940 'product'>";
    tagName = ddd;
}),
<Tags: 0x6000000a5ca0> (entity: Tags; id: 0x40002b <x-coredata://B7756C1E-B9F2-4C57-A1FA-272478C4D6A6/Tags/p1> ; data: {
    category = "0x40000b <x-coredata://B7756C1E-B9F2-4C57-A1FA-272478C4D6A6/Categories/p1>";
    product = "<relationship fault: 0x6080000283e0 'product'>";
    name = " ";
}),
<Tags: 0x6000000a76e0> (entity: Tags; id: 0x180002b <x-coredata://B7756C1E-B9F2-4C57-A1FA-272478C4D6A6/Tags/p6> ; data: {
    category = "0x40000b <x-coredata://B7756C1E-B9F2-4C57-A1FA-272478C4D6A6/Categories/p1>";
    product = "<relationship fault: 0x60800002a620 'product'>";
    name = cccc;
})
)

Any of you knows what I'm doing wrong or how can I do this?

I'll really appreciate you help


Solution

  • The content array contains managed objects for the Tags entity. Those objects do have a name property, but they don't have a length property.

    If you want to construct a sort descriptor that sorts by the length of the name, you should use the key path name.length. So:

    NSSortDescriptor *lengthSorter = [NSSortDescriptor sortDescriptorWithKey:@"name.length" ascending:YES];
    

    Also, the sort descriptors should be set on the array controller. So, where you wrote:

    [self.nameAC.content setSortDescriptors:@[lengthSorter, nameSortDescriptor]];
    

    it should be:

    [self.nameAC setSortDescriptors:@[lengthSorter, nameSortDescriptor]];
    

    or just:

    self.nameAC.sortDescriptors = @[lengthSorter, nameSortDescriptor];