Sorting NSNumbers(Scores) from .plist NSDictionary

0

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!

iphone
objective-c
sorting
plist
asked on Stack Overflow Nov 18, 2011 by Gamer • edited Nov 18, 2011 by Gamer

3 Answers

1

Per your description, highscoredata is an array of NSDictionarys. 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 NSNumbers, which know how to compare themselves.

answered on Stack Overflow Nov 18, 2011 by Tommy • edited Nov 18, 2011 by Tommy
0

It seems that id num1 and id num2 that you are passing to function intSort are not NSNumber. They seems to be NSDictionary object.

answered on Stack Overflow Nov 18, 2011 by Ilanchezhian
0

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.

answered on Stack Overflow Nov 18, 2011 by Ajeet Pratap Maurya

User contributions licensed under CC BY-SA 3.0