cowfaboo
cowfaboo

Reputation: 709

How to sort GKTurnBasedMatch by most recently active?

I am creating a simple word game with a menu screen in which I am displaying all of the user's active matches. I would like to sort this array of matches in order from most recently to least recently active, but the only timestamp property associated with players taking turns is a property of GKTurnBasedParticipant...GKTurnBasedMatch has no useful sorting property.

GKTurnBasedMatch has an array of GKTurnBasedParticipant objects as a property, so I would certainly be able to come up with some sort of solution, but I can't think of anything that wouldn't be really messy and inefficient. Is there any way something simple like NSPredicate could be used in a case like this to drill down into each array of participants, look at the latest timestamp and sort all the matches in one go?

Upvotes: 4

Views: 465

Answers (2)

Zelko
Zelko

Reputation: 3961

Sort turn-based matches by last turn of current participant

[GKTurnBasedMatch loadMatchesWithCompletionHandler:^(NSArray *matches, NSError *error)
 {
     NSString *descriptorKey = @"currentParticipant.lastTurnDate";

     NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:descriptorKey
                                                                      ascending:NO];
     
     NSArray *sortedMatches = [matches sortedArrayUsingDescriptors:@[sortDescriptor]];
 }];



Sort turn-based matches by date created

[GKTurnBasedMatch loadMatchesWithCompletionHandler:^(NSArray *matches, NSError *error)
 {
     NSString *descriptorKey = @"creationDate";

     NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:descriptorKey
                                                                      ascending:NO];
     
     NSArray *sortedMatches = [matches sortedArrayUsingDescriptors:@[sortDescriptor]];
 }];

Upvotes: 0

Tim
Tim

Reputation: 8399

I don't have an NSPredicate-based solution, or probably anything as elegant as you had hoped, but I ran into the same issue and wrote my own solution and it wasn't actually that bad.

My solution is for a game that can only have two participants, so modify accordingly, but here is the code I ended up using:

[myGamesArray sortUsingComparator:^NSComparisonResult(CHGame *game1, 
                                                      CHGame *game2) {

    if (YES == [game1 localPlayersTurn] && NO == [game2 localPlayersTurn]) {
        return NSOrderedAscending;
    } else if (NO == [game1 localPlayersTurn] && YES == [game2 localPlayersTurn]) {
        return NSOrderedDescending;
    }

    NSDate *lm1 = [game1.match lastMove];
    NSDate *lm2 = [game2.match lastMove];
    if (lm1 != nil && lm2 != nil) {
        return [lm1 compare:lm2];
    }

    return NSOrderedSame;

}];

where CHGame is a custom class I built for my games (which have a GKTurnBasedMatch match property), and the instance method localPlayersTurn returns a BOOL indicating whether or not it is the local participant's turn or not.

And then I wrote a lastMove method in a category on GKTurnBasedMatch:

- (NSDate *)lastMove {
    GKTurnBasedParticipant *localParticipant, *otherParticipant;
    NSDate *lastMove;

    for (GKTurnBasedParticipant *participant in self.participants) {
        if (YES == [participant.playerID isEqualToString:[GKLocalPlayer localPlayer].playerID]) {
            localParticipant = participant;
        } else {
            otherParticipant = participant;
        }
    }

    if (localParticipant == self.currentParticipant) {
        lastMove = otherParticipant.lastTurnDate;
    } else {
        lastMove = localParticipant.lastTurnDate;
    }

    return lastMove;
}

Again, this only works for two total participants, but would be easy to modify for any number of them.

Hope this helps even though it's not exactly what you asked for.

Upvotes: 3

Related Questions