Reputation:
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
Upvotes: 2
Views: 54
Reputation: 1995
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];
.
Upvotes: 2