2
votes

I have already figured out how to save NSInteger values in my spritekit game but now that I'm attempting to save an NSString value, my game keeps crashing. The error I get is:

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFConstantString string]: unrecognized selector sent to instance 0xe66c58`

My Code:

#import "GameState.h"

@implementation GameState

+ (instancetype)sharedInstance
{
    static dispatch_once_t pred = 0;
    static GameState *_sharedInstance = nil;

    dispatch_once( &pred, ^{
        _sharedInstance = [[super alloc] init];
    });
    return _sharedInstance;
}


- (id) init
{
    if (self = [super init]) {
        // Init
        _score = 0;
        _highScore = 0;
        _spaceShipUpgrades = 0;
        _activeShip = nil;

        // Load game state
        NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
        id highScore = [defaults objectForKey:@"highScore"];
        if (highScore) {
            _highScore = [highScore intValue];
        }
        id spaceShipUpgrades = [defaults objectForKey:@"spaceShipUpgrades"];
        if (spaceShipUpgrades){
            _spaceShipUpgrades = [spaceShipUpgrades intValue];
        }
        id activeShip = [defaults objectForKey:@"activeShip"];
        if (activeShip){
            _activeShip = [activeShip string];
        }
    }
    return self;
}

- (void) saveState {
    // Update highScore if the current score is greater
    _highScore = MAX(_score, _highScore);

    // Store in user defaults
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    [defaults setObject:[NSNumber numberWithInt:_spaceShipUpgrades] forKey:@"spaceShipUpgrades"];
    [defaults setObject:[NSNumber numberWithInt:_highScore] forKey:@"highScore"];
    [defaults setObject:[NSString stringWithString:_activeShip] forKey:@"activeShip"];
    [[NSUserDefaults standardUserDefaults] synchronize];
}

@end
1
What type is _activeShip and did you check if it's nil?0x141E

1 Answers

3
votes

The problem is most likely caused by [activeShip string]. If it is a string, it does not respond to the selector string which subsequently crashes your application. As the error says, you are sending string to __NSCFConstantString which has no such method.

If activeShip in this context is always an NSString, simply use it as is and don't send it a string message. You can log an object's class with

NSLog(@"Class of object is %@.", NSStringFromClass([anObject class]));

Or check for class type in general using:

if ([object isKindOfClass:[NSString class]]) {
    // ...
}

As general remark I would replace _sharedInstance = [[super alloc] init]; with _sharedInstance = [[GameState alloc] init];.