Сортировка NSMutableArray с пользовательскими объектами «перезаписывает» некоторые объекты - PullRequest
0 голосов
/ 08 июня 2009

Для небольшого приложения для iPhone, которое я делаю, я хочу отсортировать NSMutableArray.

Я нашел 2 способа сделать это, но оба они приводят к одному и тому же. Сортировка массива приведет к тому, что некоторые объекты будут «перезаписывать» друг друга.

Во-первых, вот мой код:

AppDelegate.h

NSMutableArray* highScores;

Где-то внизу этого AppDelegate.h я также делаю эту переменную свойством, чтобы иметь доступ к ней из разных классов:

@property (retain, nonatomic) NSMutableArray* highScores;

Когда мое приложение запускается, я считываю рекорды из файла и импортирую их в свой NSMutableArray.

AppDelegate.m

NSMutableData* data = [NSData dataWithContentsOfFile:highScoresPath];
NSKeyedUnarchiver* decoder = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
self.highScores = [decoder decodeObjectForKey:@"highscoresArray"];

Объекты, которые я храню в этом NSMutableArray, относятся к типу HighScore.

HighScore.h

@interface HighScore : NSObject {

    int score;
    int roundsPlayed;
    int wrongAnswers;

    NSString* name;

    NSDate* datetime;
}

@property int score;
@property int roundsPlayed;
@property int wrongAnswers;
@property (nonatomic, copy) NSDate* datetime;

@property (nonatomic, copy) NSString* name;

- (id) init;
- (void) update:(int)roundScore:(BOOL) correct;

@end

HighScore.m

#import "HighScore.h"

@implementation HighScore

@synthesize score, roundsPlayed, wrongAnswers, name, datetime;

- (id) init
{
    self.name = @"";
    self.score = 0;
    self.roundsPlayed = 0;
    self.wrongAnswers = 0;

    self.datetime = [NSDate date];

    return self;
}

- (void) update:(int)roundScore:(BOOL) correct
{
    self.score += roundScore;

    if (!correct)
        self.wrongAnswers++;

    self.roundsPlayed++;
    self.datetime = [NSDate date];
}

- (id) initWithCoder:(NSCoder *) decoder 
{   
    self.name = [[decoder decodeObjectForKey:@"name"] retain];
    self.score = [decoder decodeIntForKey:@"score"];
    self.roundsPlayed = [decoder decodeIntForKey:@"roundsPlayed"];
    self.wrongAnswers = [decoder decodeIntForKey:@"wrongAnswers"];
    self.datetime = [[decoder decodeObjectForKey:@"datetime"] retain];

    return self;
}

- (void) encodeWithCoder:(NSCoder *)encoder 
{
    [encoder encodeObject:self.name forKey:@"name"];
    [encoder encodeInt:self.score forKey:@"score"];
    [encoder encodeInt:self.roundsPlayed forKey:@"roundsPlayed"];
    [encoder encodeInt:self.wrongAnswers forKey:@"wrongAnswers"];
    [encoder encodeObject:self.datetime forKey:@"datetime"];
}

- (NSComparisonResult) compareHighscore:(HighScore*) h
{

    return [[NSNumber numberWithInt:self.score] compare:[NSNumber numberWithInt:h.score]];
}

@end

Теперь, когда я пытаюсь отсортировать мой массив, используя следующий код:

NSArray *sortedArray;
sortedArray = [highScores sortedArrayUsingSelector:@selector(compareHighscore:)];

Это как-то портит мой массив рекордов, я получаю X баллов рекордов с тем же счетом и именем.

Что я делаю не так?

Ответы [ 4 ]

1 голос
/ 09 июня 2009

Я замечаю, что в вашем initWithCoder: методе вы этого не делаете:

if (self = [super initWithCoder:coder]) {
    // Decode your stuff here
}

То же самое с вашим обычным init методом. Должен быть звонок на [super init].

Кроме того, поскольку вы определили свои строковые свойства как copy и используете синтаксис свойства, нет необходимости retain их. Они будут сохранены для вас синтезированным средством доступа.

В противном случае ваш код выглядит нормально для меня. Просто помните: каждый метод init всегда должен вызывать метод super init....

1 голос
/ 08 июня 2009

Вы пытаетесь сортировать, используя @selector(compare:), а не @selector(compareHighscore:), что, как я полагаю, было вашим намерением.

0 голосов
/ 24 февраля 2014

Опубликовать фактическое сравнениеHighscore: метод. Самое главное, что он должен быть согласованным, то есть если a <= b и b <= c, то a <= c, а если a <b и b <c, то a <c. Если вам удалось написать метод сравнения, который не согласован, все может произойти. </p>

0 голосов
/ 08 июня 2009

попробуй
sortedArray = [highScores sortedArrayUsingSelector: @selector ( compareHighscore: )];

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