Hi all, Following along in the documentation using "sortedArrayUsingFunction", I cannot seem to to be able to get the Array to sort as I expect. So, here is the code...in a command line ap for simplicity. I would have expected the last 2 sorts to be inverse of the other, but both sorts are the same. I **think** I have pretty carefully copied the examples from the docs...so would really like to get some insight. Thanks as always. Code: #import <Foundation/Foundation.h> NSInteger alphabeticSort(id string1, id string2, void *reverse) { if (( NSInteger *) reverse == NO) { return [string2 localizedCaseInsensitiveCompare:string1]; } return [string1 localizedCaseInsensitiveCompare:string2]; } int main (int argc, const char * argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; NSMutableArray *anArray = [NSMutableArray arrayWithObjects:@ "i", @"a", @"d", @"b", @"c", @"e",@"g",@"L", nil]; NSLog(@"anArray:%@", anArray); NSArray *sortedArray; int reverseSort = NO; sortedArray = [anArray sortedArrayUsingFunction:alphabeticSort context:&reverseSort]; NSLog(@"Sort using function: \"NO\" %@", sortedArray); reverseSort = YES; sortedArray = [anArray sortedArrayUsingFunction:alphabeticSort context:&reverseSort]; NSLog(@"Sort using function:\"YES\" %@", sortedArray); [pool drain]; return 0; }
You pass the address of an int, accept it as void *, the cast to an NSInteger *, then compare it to YES and NO without dereferencing. I think a dereference would fix it, but also make the types agree. NSInteger won't always be typedef'd to int. -Lee
Hmmm??? I wonder if something has changed since they published this example, as it is pretty much word for word from their docs. http://developer.apple.com/mac/libr...lections/Articles/sortingFilteringArrays.html
Congratulation, you found a bug in Apple's code. I tried compiling and running their code as given, and it produces the desired output (sorted in ascending order, not reversed), but it does so for the wrong reasons. A simple test case to show the bug: change reverseSort to YES, recompile and rerun, and the same ascending-order output is produced. There are several bugs in Apple's code, which combine to give the appearance of correctness: 1. the reverseSort flag is passed by reference, i.e. a pointer, but the void* received by the function is not dereferenced, i.e. the pointer itself is compared to NO, not the value pointed to. 2. the conditional logic in the sort-ordering function is inverted. The same bug(s) occurs in other samples on the web page, although with Bool pointer. There is a feedback form at the bottom of Apple's web page. I suggest sending them feedback that their example is wrong, and describe why. You can point them to this MacRumors thread. Here's a simple way to start fixing your posted code: Code: NSInteger alphabeticSort(id string1, id string2, void *reverse) { int reverseSort = * ((int*)reverse); if (reverseSort) ... This fixes both bugs: 1. it dereferences the pointer to get the flag, 2. it uses the correct sort-ordering logic (reverseSort non-zero produces a reversed sort). You could also simplify the code to pass an actual YES/NO flag, rather than by reference. This will need a type-cast when invoking the sorting method, and a corresponding change in the sort-ordering function.
It definitely seems wrong to me: Code: #import <Foundation/Foundation.h> NSInteger alphabeticSort(id string1, id string2, void *reverse) { if ((*(int *) reverse) == NO) { return [string2 localizedCaseInsensitiveCompare:string1]; } return [string1 localizedCaseInsensitiveCompare:string2]; } int main (int argc, const char * argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; NSMutableArray *anArray = [NSMutableArray arrayWithObjects:@ "i", @"a", @"d", @"b", @"c", @"e",@"g",@"L", nil]; NSLog(@"anArray:%@", anArray); NSArray *sortedArray; int reverseSort = NO; sortedArray = [anArray sortedArrayUsingFunction:alphabeticSort context:&reverseSort]; NSLog(@"Sort using function: \"NO\" %@", sortedArray); reverseSort = YES; sortedArray = [anArray sortedArrayUsingFunction:alphabeticSort context:&reverseSort]; NSLog(@"Sort using function:\"YES\" %@", sortedArray); [pool drain]; return 0; } I think with that change (i didn't test it) it should work. -Lee
Yep..it does. Rare to find an issue in the docs...I bet it has been there for years. Thanks Lee...I knew I could rely on you!!!
They should send you an iTunes gift-card or something every time you find a bug. Or run it like Chucky-Cheese where you bank up your tickets and can buy bigger/better prizes the more you have. Save up 500 tickets and you get your own personal official Apple objective-c oompa-loompa.
Just to clarify, but Lee's code still has the conditional-logic in the function inverted. Sample output: Code: 2010-03-18 13:59:30.454 a.out[8082] anArray:(i, a, d, b, c, e, g, L) 2010-03-18 13:59:30.470 a.out[8082] Sort using function: "NO" (L, i, g, e, d, c, b, a) 2010-03-18 13:59:30.470 a.out[8082] Sort using function:"YES" (a, b, c, d, e, g, i, L) The one labeled "NO" should be ascending order, but it's descending. And vice versa for the one labeled "YES". To fix it: Code: NSInteger alphabeticSort(id string1, id string2, void *reverse) { if ((*(int *) reverse))