ios - Sorting NSArray, NSComparator block vs. NSSortDescriptor, with null values -


i've been using block based approach sort nsarray... however, i'd noticed sort-related bug started investigate.

background: i'm dealing nsarray of ekreminder objects, have creationdate property. want sort reminders descending creationdate (newest reminders, first).

this previous code:

// nsarray* fetchedreminders... contents pulled reminder calendars...  nsarray* sortedarray = [fetchedreminders sortedarrayusingcomparator:^nscomparisonresult(id a, id b) {     nsdate* first = [(ekreminder*)a creationdate];     nsdate* second = [(ekreminder*)b creationdate];     return [second compare:first]; }]; 

that code, believe, correct. however, ended reminders in database had null creation date. introduced bug - resulting sort incorrect. null values neither @ beginning or end, , seems having nulls in array messed comparison approach, many of reminders out of sequence.

nssortdescriptor

so, tried swapping out block-based approach in favour of sortedarrayusingdescriptors. here's current code:

// nsarray* fetchedreminders... contents pulled reminder calendars...  nssortdescriptor* sortdescriptor; sortdescriptor = [[nssortdescriptor alloc] initwithkey:@"creationdate" ascending:no]; nsarray* sortdescriptors = [nsarray arraywithobject:sortdescriptor]; nsarray* sortedarray = [fetchedreminders sortedarrayusingdescriptors:sortdescriptors]; 

this works.

(with current data, 101 reminders, 6 of them have null creation dates , they're placed @ end. other reminders in correct sequence).

questions

first, doing wrong sortedarrayusingcomparator approach?

if not, expected these different approaches handle nulls differently?

in case, make nssortdescriptor approach preferred method, if can potentially have nulls in data?

the core issue you're running here you're not manually handling null values in block pass sortedarrayusingcomparator:. depending on values block gets called with, first can nil, second can nil, or both can nil.

any message sent nil returns equivalent 0 value (e.g. method returning float, when sent nil returns 0.0f, method returning int when sent nil returns 0, , method returning object sent nil returns nil). means have following cases:

this means call being made across values in array, values being returned non-sensical (e.g. [nil compare:[nsdate date]] returns 0, equivalent nsorderedsame, not true), not mention results returned undefined calls.

in effect, these invalid values being sorted strange places in array. if had defined behavior should happen if either value nil, you'd consistent behavior.

the following code makes sorting behavior consistent (and should give similar behavior sort descriptors method above):

nsarray* sortedarray = [fetchedreminders sortedarrayusingcomparator:^nscomparisonresult(id a, id b) {     nsdate* first = [(ekreminder*)a creationdate];     nsdate* second = [(ekreminder*)b creationdate];     if (!first && !second) {         // nils have same relative ordering         return nsorderedsame;     } else if (!first) {         // second not nil; send first toward end of array         return nsordereddescending;        } else if (!second) {         // first not nil; send second toward end of array         return nsorderedascending;     } else {         // neither nil; valid         return [second compare:first];     } }]; 

Comments

Popular posts from this blog

Delphi XE2 Indy10 udp client-server interchange using SendBuffer-ReceiveBuffer -

Qt ActiveX WMI QAxBase::dynamicCallHelper: ItemIndex(int): No such property in -

Enable autocomplete or intellisense in Atom editor for PHP -