Сортировка NSNumbers (Scores) из .plist NSDictionary - PullRequest
0 голосов
/ 18 ноября 2011

У меня есть файл highscore.plist с типом NSDictionary из 5 элементов, каждый из которых содержит NSNumber - оценка и String - Имя,

Я хочу отсортировать оценки в порядке убывания.Это то, что я пытаюсь сделать:

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;
}

Это ошибка, которую я получаю:

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'

Но когда я пытаюсь запустить его на симуляторе (iOS), он падает, яновичок в Objective C, я думаю, что я не делаю это правильно при сравнении NSNumber (баллы) в массиве.Любая помощь будет оценена.Спасибо!

Ответы [ 3 ]

1 голос
/ 18 ноября 2011

Согласно вашему описанию, highscoredata - это массив NSDictionary с. Таким образом, в результате вашего вызова sortedArrayUsingFunction:context вызывается intSort для сравнения словарей. Согласно сообщению об ошибке на консоли, NSDictionary не реализует intValue.

Чтобы настроить свой код напрямую, попробуйте:

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];

...

Таким образом, сравниваются два словаря, извлекая из каждого NSNumber, представляющий счет, и сравнивая его.

NSNumber фактически реализует compare: для себя, поэтому более компактная версия будет:

NSInteger intSort(id num1, id num2, void *context) {

    NSNumber *v1 = [num1 objectForKey:@"score"];
    NSNumber *v2 = [num2 objectForKey:@"score"];

    return [v1 compare:v2];
}

Основываясь на этом, из-за того, как ключевые пути работают в Objective-C, еще более короткая версия будет:

NSArray *highscoredata = [[NSArray alloc] initWithContentsOfFile:location];

NSSortDescriptor *sortDescriptor = 
      [NSSortDescriptor sortDescriptorWithKey:@"score" ascending:YES];

self.sortedhighscores = [highscoredata
      sortedArrayUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];

Нет необходимости в intSort функции вообще - NSDictionary знает, как искать что-то с помощью ключевого «счетчика» и что он ищет, это NSNumber s, которые умеют сравнивать себя.

0 голосов
/ 18 ноября 2011

Сортируйте ваши рекорды по убыванию, используйте этот код

     NSSortDescriptor* sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:nil ascending:NO selector:@selector(localizedCompare:)];

      NSArray* sortedArray = [highScoreArray sortedArrayUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];

Здесь мы используем localizedCompare: для сравнения строк и передачи NO в возрастающую опцию: для сортировки в порядке убывания.

0 голосов
/ 18 ноября 2011

Кажется, что id num1 и id num2, которые вы передаете function intSort, не NSNumber.Похоже, это объект NSDictionary.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...