I have a highscore.plist file with type NSDictionary of 5 items each containing NSNumber - score and String - Name ,
I want to sort scores in descending order . This is what i am trying to do :
NSString *location = [[NSBundle mainBundle] pathForResource:@"HighScores" ofType:@"plist"];
NSArray *highscoredata = [[NSArray alloc] initWithContentsOfFile:location];
self.sortedhighscores = [highscoredata sortedArrayUsingFunction:intSort context:0];
//intSort function :
NSInteger intSort(id num1, id num2, void *context) {
int v1 = [num1 intValue];
int v2 = [num2 intValue];
if (v1 < v2)
return NSOrderedAscending;
else if (v1 > v2)
return NSOrderedDescending;
else
return NSOrderedSame;
}
This is the error i receive :
2011-11-18 12:36:25.574 Test[27723:207] -[__NSCFDictionary intValue]: unrecognized selector sent to instance 0x4b66d50
2011-11-18 12:36:25.576 Test[27723:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFDictionary intValue]: unrecognized selector sent to instance 0x4b66d50'
*** Call stack at first throw:
(
0 CoreFoundation 0x00f355a9 __exceptionPreprocess + 185
1 libobjc.A.dylib 0x01089313 objc_exception_throw + 44
2 CoreFoundation 0x00f370bb -[NSObject(NSObject) doesNotRecognizeSelector:] + 187
3 CoreFoundation 0x00ea6966 ___forwarding___ + 966
4 CoreFoundation 0x00ea6522 _CF_forwarding_prep_0 + 50
5 Test 0x000035e8 intSort + 36
6 CoreFoundation 0x00e9c3cf __CFSimpleMergeSort + 591
7 CoreFoundation 0x00e9c1c6 __CFSimpleMergeSort + 70
8 CoreFoundation 0x00e9c06c CFSortIndexes + 268
9 CoreFoundation 0x00ebf42c -[NSArray sortedArrayWithOptions:usingComparator:] + 380
10 CoreFoundation 0x00ebf21a -[NSArray sortedArrayUsingFunction:context:] + 106
11 Test 0x000036f7 -[HighScore_ViewController viewDidLoad] + 192
12 UIKit 0x00372089 -[UIViewController view] + 179
13 UIKit 0x00373a3d -[UIViewController viewControllerForRotation] + 63
14 UIKit 0x0036f988 -[UIViewController _visibleView] + 90
15 UIKit 0x0061193c -[UIClientRotationContext initWithClient:toOrientation:duration:andWindow:] + 354
16 UIKit 0x002e981e -[UIWindow _setRotatableClient:toOrientation:updateStatusBar:duration:force:] + 954
17 UIKit 0x00571619 -[UIWindowController transition:fromViewController:toViewController:target:didEndSelector:] + 1381
18 UIKit 0x0037665d -[UIViewController presentModalViewController:withTransition:] + 3478
19 Test 0x0000296b -[Test_ViewController ShowLeaderboardsModal:] + 198
20 UIKit 0x002c24fd -[UIApplication sendAction:to:from:forEvent:] + 119
21 UIKit 0x00352799 -[UIControl sendAction:to:forEvent:] + 67
22 UIKit 0x00354c2b -[UIControl(Internal) _sendActionsForEvents:withEvent:] + 527
23 UIKit 0x003537d8 -[UIControl touchesEnded:withEvent:] + 458
24 UIKit 0x002e6ded -[UIWindow _sendTouchesForEvent:] + 567
25 UIKit 0x002c7c37 -[UIApplication sendEvent:] + 447
26 UIKit 0x002ccf2e _UIApplicationHandleEvent + 7576
27 GraphicsServices 0x0188d992 PurpleEventCallback + 1550
28 CoreFoundation 0x00f16944 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 52
29 CoreFoundation 0x00e76cf7 __CFRunLoopDoSource1 + 215
30 CoreFoundation 0x00e73f83 __CFRunLoopRun + 979
31 CoreFoundation 0x00e73840 CFRunLoopRunSpecific + 208
32 CoreFoundation 0x00e73761 CFRunLoopRunInMode + 97
33 GraphicsServices 0x0188c1c4 GSEventRunModal + 217
34 GraphicsServices 0x0188c289 GSEventRun + 115
35 UIKit 0x002d0c93 UIApplicationMain + 1160
36 Test 0x00001f3c main + 102
37 Test 0x00001ecd start + 53
)
terminate called after throwing an instance of 'NSException'
But when I try to run it on Simulator (iOS) it crashes, Im new to Objective C , I think im not doing it right when comparing NSNumber(scores) in array . Any help would be appreciated . Thanks!
Per your description, highscoredata
is an array of NSDictionary
s. So the result of your call to sortedArrayUsingFunction:context
is that intSort
is called to compare dictionaries. As per the error reported on the console, NSDictionary
does not implement intValue
.
To adjust your code directly, try:
NSInteger intSort(id num1, id num2, void *context) {
// assuming the numerical score is in the dictionary
// under the key 'score'
int v1 = [[num1 objectForKey:@"score"] intValue];
int v2 = [[num2 objectForKey:@"score"] intValue];
...
So that compares two dictionaries by retrieving from each the NSNumber representing the score, and comparing that.
NSNumber actually implements compare:
for itself, so a more compact version would be:
NSInteger intSort(id num1, id num2, void *context) {
NSNumber *v1 = [num1 objectForKey:@"score"];
NSNumber *v2 = [num2 objectForKey:@"score"];
return [v1 compare:v2];
}
Building on that, because of the way key paths work in Objective-C, an even shorter version would be:
NSArray *highscoredata = [[NSArray alloc] initWithContentsOfFile:location];
NSSortDescriptor *sortDescriptor =
[NSSortDescriptor sortDescriptorWithKey:@"score" ascending:YES];
self.sortedhighscores = [highscoredata
sortedArrayUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];
No need for an intSort
function at all — NSDictionary
knows how to look something up with the key "score" and the things that it looks up are NSNumber
s, which know how to compare themselves.
It seems that id num1
and id num2
that you are passing to function intSort
are not NSNumber
. They seems to be NSDictionary object.
Sort your highscore data in descending order use this code
NSSortDescriptor* sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:nil ascending:NO selector:@selector(localizedCompare:)];
NSArray* sortedArray = [highScoreArray sortedArrayUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];
Here we use localizedCompare: to compare the strings, and pass NO to the ascending: option to sort in descending order.
User contributions licensed under CC BY-SA 3.0