pdmorrill pdmorrill - 1 year ago 79
Objective-C Question

Encoding, decoding, and editing a NSMutableArray with NSCoding

I followed along with Ray Wenderlich's tutorial for saving game data using a singleton and NSCoding (http://www.raywenderlich.com/63235/how-to-save-your-game-data-tutorial-part-1-of-2). Everything they did I've been able to use for NSStrings (changing value, storing, using in my project). I tried to make an NSMutableArray so I could add to and save a list of strings, though, and it didn't work. There is probably a very simple solution to this, so thanks in advance for putting up with a newbie.

My code:

in RWGameData.h (my singleton for using game data):

@property (nonatomic, strong) NSMutableArray *dataArray;

in RWGameData.m, after

static NSString* const GameDataArrayofValues = @"dataArray";

-(void)encodeWithCoder:(NSCoder *)encoder {
[encoder encodeObject:self.dataArray forKey:GameDataArrayofValues];

-(instancetype)initWithCoder:(NSCoder *)decoder {
self = [self init];
if (self) {
_dataArray = [[decoder decodeObjectForKey:GameDataArrayofValues] mutableCopy];
return self;

(there's also all the other code from that tutorial, like a save method etc.)

in myGame.m

[[RWGameData sharedGameData].dataArray addObject:@"objectString"];
[[RWGameData sharedGameData] save];

Logging the contents of the array right after this shows it as empty.
[RWGameData sharedGameData].dataArray
accepts the
call because I created it as an NSMutableArray, but it seems like it isn't actually going through.

Any ideas?

Answer Source

My guess is _dataArray is nil.

You should add code to your initWithCoder that checks to see if it was able to read array data. If not, _dataArray will be nil. In that case you should initialize an empty mutable array.

Your updated initWithCoder might look like this:

-(instancetype)initWithCoder:(NSCoder *)decoder {
  self = [self init];
  if (self) 
    _dataArray = [[decoder decodeObjectForKey:GameDataArrayofValues] mutableCopy];
    if (_dataArray)
      _dataArray = [[NSMutableArray alloc] init];
  return self;

Likewise you need to implement a "regular" init method that sets _dataArray to an empty mutable array.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download