Objective-C NSUserDefaults: HighScoreManager, почему это не работает?

Мое приложение не сохраняет и не загружает данные, оно просто падает, интересно, что я делаю неправильно в своем классе High Score Manager.

Я собираюсь опубликовать файлы .h и .m моего класса:

.h

#import <Foundation/Foundation.h>

@interface Score : NSObject
{
    NSString *name;
    NSNumber *score;
}

@property (assign, nonatomic) NSString *name;
@property (assign, nonatomic) NSNumber *score;

+ (Score *) score: (NSNumber *)score_ name: (NSString *)name_;
- (id) initWithScore: (NSNumber *)score_ name: (NSString *)name_;

@end

@interface HighScoreManager : NSObject
{
    NSArray *an_;
    NSArray *as_;
    BOOL loaded;
}

- (void) load;
- (BOOL) noScores;
- (NSArray *) sortedScores;
- (void) add: (NSString *)name score: (NSNumber *)score;

@end

.m

#import "HighScoreManager.h"

@implementation Score
@synthesize name, score;

+ (Score *) score: (NSNumber *)score_ name: (NSString *)name_
{
    return [[[Score alloc] initWithScore: score_ name: name_] autorelease];
}

- (id) initWithScore: (NSNumber *)score_ name: (NSString *)name_
{
    if((self = [super init]))
    {
        score = score_;
        name = name_;
    }

    return self;
}

@end

@implementation HighScoreManager

- (id) init
{
    if((self = [super init]))
    {
        loaded = NO;
    }

    return self;
}

- (void) load
{
    if(!loaded) {
        NSUserDefaults *NSUD = [NSUserDefaults standardUserDefaults];
        [NSUD synchronize];
        an_ = [NSUD arrayForKey: @"game.score.names"];
        as_ = [NSUD arrayForKey: @"game.score.scores"];
        [NSUD release];

        loaded = YES;
    }
}

- (BOOL) noScores
{
    [self load];
    return [an_ count] < 1;
}

- (NSArray *) sortedScores
{
    [self load];
    NSMutableArray *scoresObj = [NSMutableArray array];

    for(NSUInteger i = 0; i < [an_ count]; i++)
    {
        [scoresObj addObject: [Score score: [as_ objectAtIndex: i] name: [an_ objectAtIndex: i]]];
    }

    NSSortDescriptor *sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"score" ascending: NO] autorelease];
    NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];

    return [scoresObj sortedArrayUsingDescriptors: sortDescriptors];
}

- (void) add: (NSString *)name score: (NSNumber *)score
{
    NSUserDefaults *NSUD2 = [NSUserDefaults standardUserDefaults];
    [NSUD2 setObject: [[NSUD2 arrayForKey: @"game.score.names"] arrayByAddingObject: name] forKey: @"game.score.names"];
    [NSUD2 setObject: [[NSUD2 arrayForKey: @"game.score.scores"] arrayByAddingObject: score] forKey: @"game.score.scores"];
    [NSUD2 synchronize];
}

- (void) dealloc
{
    [an_ release];
    [as_ release];
    [super dealloc];
}

@end

Как я пытался использовать класс

    HighScoreManager *HSM1 = [HighScoreManager new];
    [HSM1 add: @"Johannes" score: [NSNumber numberWithInt: 1298]];
    [HSM1 add: @"Johannes" score: [NSNumber numberWithInt: 8723]];
    [HSM1 add: @"Johannes" score: [NSNumber numberWithInt: 3283]];
    [HSM1 add: @"Johannes" score: [NSNumber numberWithInt: 1763]];
    [HSM1 add: @"Johannes" score: [NSNumber numberWithInt: 9931]];

    HighScoreManager *HSM = [HighScoreManager new];

    // Check if there even are any high scores.
    if([HSM noScores])
    {
        CCLabel *noScoresYet = [CCLabel labelWithString: @"There are no scores yet." fontName: @"Helvetica" fontSize: 36];
        noScoresYet.position = ccp(win.width / 2, win.height / 2);
        [noScoresYet setColor: ccc3(0, 0, 0)];
        [self addChild: noScoresYet];
    } else
    {
        // Oh look, there were some high scores!

    }

    [HSM release];

Несмотря на то, что я «сохраняю» баллы, когда я ухожу со страницы «Результаты» и возвращаюсь назад, приложение вылетает. Я не совсем уверен, что я делаю неправильно или почему он не сохраняется


Я получаю это, когда происходит сбой "_class_getMethodNoSuper_nolock", а иногда и objC_send или что-то в этом роде.


person Johannes Jensen    schedule 28.07.2010    source источник
comment
Сейчас я делаю ставку на присвоение свойств в классе Score (см. мой ответ)   -  person Ron Srebro    schedule 28.07.2010


Ответы (3)


  • Не отпускайте NSUD. Вы не создали его и не сохранили его, поэтому вы им не владеете. Это может быть причиной сбоя.

  • Вы также должны сохранить свои переменные экземпляра.

  • [NSUD2 arrayForKey: @"game.score.names"] сначала вернет nil, поэтому [[NSUD2 arrayForKey: @"game.score.names"] arrayByAddingObject: name] тоже будет nil. Вы всегда устанавливаете значения словаря равными нулю.

  • (И избегайте имен переменных, таких как «an_». Это затрудняет чтение вашего кода.)

person nschum    schedule 30.07.2010

Опишите, где именно происходит сбой, и, возможно, я смогу помочь. Я заметил по крайней мере одну проблему:

return [[[self alloc] initWithScore: score_ name: name_] autorelease];

Должно быть

return [[[Score alloc] initWithScore: score_ name: name_] autorelease];
person kubi    schedule 28.07.2010

Не тестировал ваш код, но первое, что я заметил, это ваши статические фабричные методы, которые пытаются выделить себя вместо класса Score.

Я уверен, что вам нужно:

+ (Score *) score: (NSNumber *)score_ name: (NSString *)name_
{
     return [[[Score alloc] initWithScore: score_ name: name_] autorelease];
}

Еще кое-что. Ваши свойства в классе Score объявлены как назначенные, что означает, что вы не сохраняете полученную оценку и имя, если они выходят за рамки, это также приведет к сбою вашего приложения.

person Ron Srebro    schedule 28.07.2010
comment
[self alloc] в методе класса идиоматичен. [Score alloc] необычно и звучит для меня как Javaism. Класс почти никогда не должен упоминать себя по имени в методе. Вы ничего не получаете и теряете наследство. - person Chuck; 31.07.2010
comment
Честно говоря, я никогда не возражал против того, чтобы он был написан так или на любом другом языке, если уж на то пошло. Я понимаю вашу точку зрения, но выделение не является методом экземпляра - как это может быть, экземпляр еще не создан. Я всегда думал, что obj-c способ создания объектов странный. - person Ron Srebro; 31.07.2010