Showing Game Center high scores in UILabels - iphone

I'm making a turn based iPhone game with a maximum of 2 players, in my game You can get a score which will be put in a Game center leaderboard. The next time you start the game up your highest score will be retrieved and you can make it even higher because the app counts on from that previous highscore. I found some code to get the authenticated players score But I also wanna show the score of the opponent you are playing and I was wondering how?
This is the code I found for the authenticated player (yourself)
if([GKLocalPlayer localPlayer].authenticated) {
NSArray *arr = [[NSArray alloc] initWithObjects:[GKLocalPlayer localPlayer].playerID, nil];
GKLeaderboard *board = [[GKLeaderboard alloc] initWithPlayerIDs:arr];
if(board != nil) {
board.timeScope = GKLeaderboardTimeScopeAllTime;
board.range = NSMakeRange(1, 1);
board.category = #"MY_LEADERBOARD";
[board loadScoresWithCompletionHandler: ^(NSArray *scores, NSError *error) {
if (error != nil) {
// handle the error.
NSLog(#"Error retrieving score.", nil);
}
if (scores != nil) {
NSLog(#"My Score: %i", ((GKScore*)[scores objectAtIndex:0]).value);
}
}];
}
[board release];
[arr release];
}
is there a way to modify this so it will show what I want?
Also I have a problem showing NSLog(#"My Score: %i", ((GKScore*)[scores objectAtIndex:0]).value);
in a UILabel :S
Hope someone can help me out

NSLog(#"My Score: %lld", ((GKScore*)[scores objectAtIndex:0]).value);
the score values are 64bit integers, not int's
intValue
longValue
longLongValue <<==

Related

Retrieve scores of two friends above GKLocalPlayer

I want to show a very small leaderboard snippet on my games front page, basically showing your score and the scores of two friends around you (above and below you're score). I have read through the apple documentation and cannot see a way to do this unless I specify all friends and specify a huge range to ensure I get all the friends, which I can then filter. It seems inefficient to retrieve this list especially as the user may be on mobile. How can I achieve what I want without downloading the entire list of friends and then filtering?
Here is what I currently have (without filtering)
GKLeaderboard *leaderboardRequest = [[GKLeaderboard alloc] init];
if (leaderboardRequest != nil)
{
leaderboardRequest.playerScope = GKLeaderboardPlayerScopeFriendsOnly;
leaderboardRequest.timeScope = GKLeaderboardTimeScopeAllTime;
leaderboardRequest.category = #"HighScore";
leaderboardRequest.range = NSMakeRange(1,100);
[leaderboardRequest loadScoresWithCompletionHandler: ^(NSArray *scores, NSError *error) {
if (error != nil)
{
// Handle the error.
}
if (scores != nil)
{
GKScore* myScore = leaderboardRequest.localPlayerScore;
NSLog(#"Me: %#: %d",myScore.playerID, (int)myScore.value);
// Process the score information - here I would filter
for (GKScore* score in scores)
{
NSLog(#"%#: %d",score.playerID, (int)score.value);
}
}
}];
}
The following code may help you.
From Game Center Programming Guide:
GKLeaderboard range: You can pick scores within a specific range. For example, the range [1,10] returns the best ten scores found by the query.
GKScore rank: The position of the score in the results of a leaderboard search.
ps. I couldn't test it.
Best regards.
GKLeaderboard *leaderboardRequest = [[GKLeaderboard alloc] init];
if (leaderboardRequest != nil)
{
GKScore* myScore = leaderboardRequest.localPlayerScore;
leaderboardRequest.playerScope = GKLeaderboardPlayerScopeFriendsOnly;
leaderboardRequest.timeScope = GKLeaderboardTimeScopeAllTime;
leaderboardRequest.category = #"HighScore";
leaderboardRequest.range = NSMakeRange(myScore.rank-1, myScore.rank+1);
[leaderboardRequest loadScoresWithCompletionHandler: ^(NSArray *scores, NSError *error) {
if (error != nil)
{
// Handle the error.
}
else
{
// ...
}
}];
}

Game Center Turn Based match list not showing when offline

I am using custom view to show the list of matches in my turn based game. With the custom view I am having issues showing the list of current games the player is involved when the device is offline. But when I check the game center default view the matches show fine even when offline. The code I am using to populate my array is as follows (extracted from the book by Ray Wenderlich)
[GKTurnBasedMatch loadMatchesWithCompletionHandler:^(NSArray *matches, NSError *error)
{
if (error)
{
NSLog(#"%#", error.localizedDescription);
}
else
{
NSMutableArray *myMatches = [NSMutableArray array];
NSMutableArray *otherMatches = [NSMutableArray array];
NSMutableArray *endedMatches = [NSMutableArray array];
for (GKTurnBasedMatch *m in matches)
{
GKTurnBasedMatchOutcome myOutcome;
for (GKTurnBasedParticipant *par in m.participants)
{
if ([par.playerID isEqualToString: [GKLocalPlayer localPlayer].playerID])
{
myOutcome = par.matchOutcome;
}
}
if (m.status != GKTurnBasedMatchStatusEnded && myOutcome != GKTurnBasedMatchOutcomeQuit)
{
if ([m.currentParticipant.playerID
isEqualToString:[GKLocalPlayer localPlayer].playerID])
{
[myMatches addObject:m];
}
else
{
[otherMatches addObject:m];
}
}
else
{
[endedMatches addObject:m];
}
}
// 6
allMyMatches = [[NSArray alloc]initWithObjects:myMatches,otherMatches,endedMatches, nil];
NSLog(#"%#",allMyMatches);
[self.tableView reloadData];
}
}];
Any ideas why this is happening?
loadMatchesWithCompletionHandler: will talk to the Game Center servers and I would expect it to fail if your device is offline. You are checking for error to be not nil. Is error.localizedDescription telling you you're not connected?
My bet would be that the Game Center default view will show you matches that it cached from the last time you were connected. You could do this too, but remember that you would also have to cache the matchData. Not sure how important that would be since you won't be able to submit your turn anyways.

Gamer Center leaderboard shows no scores, and each user only has access to their own score

I'm trying to make a leaderboard in my game with Game Center. I post the high score like so:
GKScore *myScoreValue = [[[GKScore alloc] initWithCategory:#"grp.high_scores"] autorelease];
myScoreValue.value = self.game.scoreMeter.score;
NSLog(#"Attemping to submit score: %#", myScoreValue);
[myScoreValue reportScoreWithCompletionHandler:^(NSError *error){
if(error != nil){
NSLog(#"Score Submission Failed");
} else {
NSLog(#"Score Submitted");
id appDelegate = [[UIApplication sharedApplication] delegate];
[appDelegate displayLeaderBoard:nil];
}
}];
I see "Score Submitted" as expecting, and it brings up the Game Center leaderboard view, but it just reads "No Scores"
I know other people have said you need at least two accounts, but I've tried with three already.
For each account, the game shows up for them in the Game Center App, and when I query for the top ten scores:
- (void) retrieveTopTenScores
{
GKLeaderboard *leaderboardRequest = [[GKLeaderboard alloc] init];
if (leaderboardRequest != nil)
{
leaderboardRequest.playerScope = GKLeaderboardPlayerScopeGlobal;
leaderboardRequest.timeScope = GKLeaderboardTimeScopeAllTime;
leaderboardRequest.range = NSMakeRange(1,10);
[leaderboardRequest loadScoresWithCompletionHandler: ^(NSArray *scores, NSError *error) {
if (error != nil)
{
NSLog(#"Error grabbing top ten: %#", error);
}
if (scores != nil)
{
NSLog(#"Top ten scores: %#", scores);
}
}];
}
}
each user only sees their own score.
So why is the leaderboard empty, and why is each user only seeing their own score?
Sandbox can be messy sometimes, but let me ask you this. Is your self.game.scoreMeter.score an int?
If so, try doing this:
myScoreValue.value = [[NSNumber numberWithInt:self.game.scoreMeter.score] longLongValue];
for setting the value of the GKScore object. Let me know if it changes anything.
Well, it turns out you need to be signed in to game center with a developer sandbox account for it to work correctly

Memory usage climbing when popping out of ALAssetslibrary during enumeration

I have an issue where I see memory usage climbing (but no obvious leaks in Instruments) in my app.
I have a test project with two viewControllers: MainViewController and PhotoViewController. The MainViewController contains a single button that simply pushes PhotoViewController via a uinavigationcontroller pushViewController method.
In PhotoViewController, I am using the ALAssetsLibrary to populate a UITableView with images. I essentially do this in two parts. First, I check to see what assetGroups are available, as I need to show images from the Camera Roll and the Photolibrary. Once that is done, I call another method to enumerate through the actual Assets.
Here is the strange behavior: if I push the PhotoViewController and let it finish the entire enumeration and populate the UITableView, and then pop out back to the MainViewController, everything is fine.
However, if I repeatedly and rapidly push and pop out of the PhotoViewCOntroller (while it hasn't yet finished enumerating and populating the UITableiew),then I see my memory usage gradually climbing until the app finally dies. I don't see any obvious leaks in Instruments.
I don't know the relevant code, but here are two methods that use to enumerate. Of course, in dealloc, I am releasing the relevant ivars.
Is there some way to cancel an enumeration upon pop?
Just as a note, I am basing my test code off this project (https://github.com/elc/ELCImagePickerController), although heavily customized. However, I just tested with that code and the same issue happens. Note that you would only see memory usage climb if you have sufficient ALAssets to enumerate. If there are too few, then it would finish enumerating beforeyou couldpop back out.
Thank you!
- (void)getAssetGroups
{
// Load Albums into assetGroups
dispatch_async(dispatch_get_main_queue(), ^
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// Group enumerator Block
void (^assetGroupEnumerator)(ALAssetsGroup *, BOOL *) = ^(ALAssetsGroup *group, BOOL *stop)
{
if (group == nil)
{
// check what data is available
if([savedPhotosGroup numberOfAssets] > 0 && [libraryGroup numberOfAssets] > 0)
{
// User has both Camera Roll and Photo Library albums
self.tableData = [NSMutableDictionary dictionaryWithObjectsAndKeys:
savedPhotoAssets, NSLocalizedString(#"PHOTOPICKER_CAMERAROLL", nil),
libraryPhotosAssets, NSLocalizedString(#"PHOTOPICKER_PHOTOLIBRARY", nil),
nil];
self.sectionKeys = [NSArray arrayWithObjects:NSLocalizedString(#"PHOTOPICKER_CAMERAROLL", nil), NSLocalizedString(#"PHOTOPICKER_PHOTOLIBRARY", nil), nil];
}
else if([libraryGroup numberOfAssets] == 0)
{
// User only has Camera Roll
self.tableData = [NSMutableDictionary dictionaryWithObjectsAndKeys:
savedPhotoAssets, NSLocalizedString(#"PHOTOPICKER_CAMERAROLL", nil),
nil];
self.sectionKeys = [NSArray arrayWithObjects:NSLocalizedString(#"PHOTOPICKER_CAMERAROLL", nil), nil];
}
else
{
//User only has Photo Library
self.tableData = [NSMutableDictionary dictionaryWithObjectsAndKeys:
libraryPhotosAssets, NSLocalizedString(#"PHOTOPICKER_PHOTOLIBRARY", nil),
nil];
self.sectionKeys = [NSArray arrayWithObjects:NSLocalizedString(#"PHOTOPICKER_PHOTOLIBRARY", nil), nil];
}
NSLog(#"Done enumerating groups");
[self performSelectorInBackground:#selector(enumeratePhotos) withObject:nil];
[self.tview performSelector:#selector(reloadData) withObject:nil afterDelay:1];
return;
}
ALAssetsGroupType groupType = [[group valueForProperty:ALAssetsGroupPropertyType] unsignedIntValue];
if(groupType == ALAssetsGroupSavedPhotos)
{
self.savedPhotosGroup = group;
}
else if(groupType == ALAssetsGroupLibrary)
{
self.libraryGroup = group;
}
};
// Group Enumerator Failure Block
void (^assetGroupEnumberatorFailure)(NSError *) = ^(NSError *error) {
NSLog(#"A problem occured %#", [error description]);
};
// Enumerate Albums
[library enumerateGroupsWithTypes: ALAssetsGroupSavedPhotos | ALAssetsGroupLibrary
usingBlock:assetGroupEnumerator
failureBlock:assetGroupEnumberatorFailure];
NSLog(#"Draining pool");
[pool drain];
});
}
-(void)enumeratePhotos {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSLog(#"enumerating photos");
[savedPhotosGroup enumerateAssetsUsingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop)
{
if(result == nil)
{
return;
}
CustomAsset *customAsset = [[[CustomAsset alloc] initWithAsset:result] autorelease];
[customAsset setParent:self];
[savedPhotoAssets addObject:customAsset];
}];
[libraryGroup enumerateAssetsUsingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop)
{
if(result == nil)
{
return;
}
CustomAsset *customAsset = [[[CustomAsset alloc] initWithAsset:result] autorelease];
[customAsset setParent:self];
[libraryPhotosAssets addObject:customAsset];
}];
NSLog(#"done enumerating photos");
[tview performSelectorOnMainThread:#selector(reloadData) withObject:nil waitUntilDone:NO];
// only do this if I want to re-select some assets
if(assetsToRestore)
{
for(NSDictionary *dict in assetsToRestore)
{
NSIndexPath *indexPathToRestore = [dict objectForKey:#"selectedAssetIndexPath"];
int tagToRestore = [[dict objectForKey:#"selectedAssetTag"] intValue];
[self selectAssetWithIndexPath:indexPathToRestore andIndex:tagToRestore];
}
}
[pool drain]; }
correct me if i'm wrong, I thought using autorelease pools was supposed to be done like this now:
#autoreleasepool {
(statements)
}
That worked for me.

game center score submission problem

i have integrate game center in my game ...and its working well but i have i new problem now :P
only one score is submit of user .. after that no score submit even its greater then posted score or less...
any idea what i have to exactly doo...
Regards
Haseeb
i use this to submit score......after being sure that the game center is available...
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
GKScore *scoreReporter = [[[GKScore alloc] initWithCategory:gameCenterCategory] autorelease];
int64_t score1 =socre;
scoreReporter.value = score1;
[scoreReporter reportScoreWithCompletionHandler:^(NSError *error) {
if (error != nil) {
NSLog(#"Submit failed");
}
else {
NSLog(#"Score Submited");
}
}];
[pool release];