0

I am working on a turn-based Game Center game. I am trying to encode a custom class for which I have already written encodeWithEncoder and initWithEncoder. Those seem to work fine, except for two arrays of other little custom objects that don't unpack. My question is, if I write little custom encodeWithEncoder and initWithEncoder methods for those classes, and make them conform to NSCoding, will they be unpacked as well? Or are you not allowed to nest encodings like that? i.e., I have an object called a Game which has an array f Hands and an array of Plays among other things. If I were to implement NSCoding for them, would I be able to unpack them as well?

EDIT: As requested, my code that isn't working:

// Implementation of the Player object.
@implementation Player

@synthesize playerID;
@synthesize displayName;

- (void)encodeWithCoder:(NSCoder*)coder
{
    [coder encodeObject:playerID forKey:@"PlayerID"];
    [coder encodeObject:displayName forKey:@"DisplayName"];
}

- (id)initWithCoder:(NSCoder*)coder
{
    self = [super init];
    if (self)
    {
        playerID = [coder decodeObjectForKey:@"PlayerID"];
        displayName = [coder decodeObjectForKey:@"DisplayName"];
    }
    return self;
}

@end

// Implementation of the Play object.
@implementation Play : NSObject

@synthesize player;
@synthesize bCard;
@synthesize playedCards;


- (void)encodeWithCoder:(NSCoder*)coder
{
    [coder encodeObject:player forKey:@"Player"];
    [coder bCard forKey:@"BCard"];
    [coder encodeObject:playedCards forKey:@"PlayedCards"];
}

- (id)initWithCoder:(NSCoder*)coder
{
    self = [super init];
    if (self)
    {
        player = [coder decodeObjectForKey:@"Player"];
        bCard = [coder decodeObjectForKey:@"BCard"];
        playedCards = [coder decodeObjectForKey:@"PlayedCards"];
    }
    return self;
}

@end

// Implementation of the Hand object.
@implementation Hand : NSObject

@synthesize owner;
@synthesize cards;

- (void)encodeWithCoder:(NSCoder*)coder
{
    [coder encodeObject:owner forKey:@"Owner"];
    [coder encodeObject:cards forKey:@"Cards"];
}

- (id)initWithCoder:(NSCoder*)coder
{
    self = [super init];
    if (self)
    {
        owner = [coder decodeObjectForKey:@"Owner"];
        cards = [coder decodeObjectForKey:@"Cards"];
    }
    return self;
}

@end

// Implementation of the Game object.
@implementation Game : NSObject

@synthesize activePlayer, judge, match, players, play, judgeID, hand, bCard, hands, plays;


// Function to pack up the game object for transmission through Game Center.
- (void) encodeWithCoder:(NSCoder *)coder
{
    // Package up all the data required to continue the game.
    if([coder allowsKeyedCoding])
    {
        [coder encodeObject:judge forKey:@"Judge"];
        [coder encodeObject:bCard forKey:@"BCard"];
        [coder encodeObject:hands forKey:@"Hands"];
        [coder encodeObject:plays forKey:@"Plays"];
    }
}

// Function to unpack a game object recieved from Game Center.
- (id) initWithCoder:(NSCoder *)coder
{
    self = [super init];
    if (self)
    {
        // Decode packed objects.
        judge = [coder decodeObjectForKey:@"Judge"];
        bCard = [coder decodeObjectForKey:@"BCard"];
        hands = [coder decodeObjectForKey:@"Hands"];
        plays = [coder decodeObjectForKey:@"Plays"];

        // Look for your hand in the hands array.
        hand = nil;
        for (int i = 0; i < [hands count]; i++)
        {
            if ([[[(Hand*)hands[i] owner] playerID] isEqualToString:GKLocalPlayer.localPlayer.playerID])
            {
                hand = hands[i];
                break;
            }
        }

        // If your hand was not found, draw a new one.
        if (!hand)
        {
            [self drawHand];
        }
    }
    return self;
}
Logan Shire
  • 5,013
  • 4
  • 29
  • 37
  • Sure, you can have "nested" encoded objects. Did you try it? – rmaddy Jun 09 '13 at 03:28
  • I wanted to know if it was possible before I took the time. So, if I have the init and encode methods defined, should this work? hands = [coder decodeObjectForKey:Hands]; plays = [coder decodeObjectForKey:Plays]; – Logan Shire Jun 09 '13 at 03:37
  • If you properly implement the `NSCoding` protocol in each class then it will work. – rmaddy Jun 09 '13 at 03:40
  • Cool. So it will handle all that for me if I have them properly defined? Then if you 'Answer' to this post I can mark it solved. – Logan Shire Jun 09 '13 at 03:42
  • EDIT: That did not work. It didn't unpack any information when I tried to do that. – Logan Shire Jun 09 '13 at 03:59
  • You need to post your relevant code that shows how you attempt to encode and decode your objects. – rmaddy Jun 09 '13 at 04:03
  • The `encodeWithCoder` method looks weird in your `Game` class. What is the point of the `judgeDict`? There seems to be a typo too. – rmaddy Jun 09 '13 at 04:17
  • Sorry to mislead you. That was something I was trying that didn't pan out. It isn't the issue and I have deleted it. – Logan Shire Jun 09 '13 at 04:19
  • Another type in the Play class? `[coder bCard forKey:@"BCard"];` Are you seeing errors or just getting nil values? – Ben Flynn Jun 09 '13 at 04:39
  • Nil values. It was never even calling the encodeWithEncoder methods of my nested classes. Now I'm just trying to do it all with dictionaries. – Logan Shire Jun 09 '13 at 05:03
  • Note that the `initWithCoder:` methods must call `self = [super initWithCoder:coder]`, not `self = [super init]`. – Martin R Jun 09 '13 at 06:12
  • Hmm. I'll test that out tomorrow. – Logan Shire Jun 09 '13 at 11:40

0 Answers0