使用自定义对象对NSMutableArray进行排序会“覆盖”某些对象

时间:2009-06-08 19:34:01

标签: iphone cocoa cocoa-touch

对于我正在制作的小型iPhone应用程序,我想对NSMutableArray进行排序。

我找到了两种方法,但它们都会产生同样的结果。对数组进行排序会导致某些对象相互“覆盖”。

首先,这是我的代码:

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

它以某种方式搞砸了我的highScores数组,我获得了一个具有相同分数和名称的X高分数。

我做错了什么?

4 个答案:

答案 0 :(得分:1)

您尝试使用@selector(compare:)排序,而不是@selector(compareHighscore:),我认为这是您的意图。

答案 1 :(得分:1)

我注意到,在你的initWithCoder:方法中,你没有这样做:

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

与常规init方法相同。需要拨打[super init]

此外,由于您将字符串属性定义为copy并且您使用的是属性语法,因此无需retain它们。它们将由合成访问器保留给您。

否则,您的代码对我来说很好。请记住:每个init方法都必须始终调用super的{​​{1}}方法。

答案 2 :(得分:0)

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

答案 3 :(得分:0)

发布实际的compareHighscore:方法。最重要的是它必须是一致的,即如果a <= b且b <= c,则a&lt; = c并且如果a&lt; = b和b&lt;然后a&lt; C。如果你设法编写一个不一致的比较方法,任何事情都可能发生。