- (void) reportScore: (int64_t) score forLeaderboardID: (NSString*) identifier
{
GKScore *scoreReporter = [[GKScore alloc] initWithLeaderboardIdentifier: identifier];
scoreReporter.value = score;
scoreReporter.context = 0;
NSArray *scores = #[scoreReporter];
[GKLeaderboard reportScores:scores withCompletionHandler:^(NSError *error) {
//Do something interesting here.
}];
}
https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/GameKit_Guide/LeaderBoards/LeaderBoards.html
On the above site, I used the above code (and the title was Reporting a score to Game Center (iOS 7)) but on the GKLeaderboard reportScores... line, I get an error saying that there is no such method. How do i fix this without using GKScore's deprecated reportScoreWithCompletionHandlerMethod?
So apple's thing had a typo. GKLeaderboard was supposed to be GKScore in the reportScores line.
Related
I'm adding Game Center functionality to my app, and I have run into something strange that I can't get my head around...
I've used this exact method (and code) in 5 games, so I can't see why it's throwing a warning message now...
I get 2x "local declaration of 'score' hides instance variable" in the ReportScore method...
The code is as follows:
-(void)reportScore{
GKScore *score = [[GKScore alloc] initWithLeaderboardIdentifier:_leaderboardIdentifier];
score.value = gameScore; //gameScore is games Score that needs submitting
[GKScore reportScores:#[score] withCompletionHandler:^(NSError *error) {
if (error != nil) {
NSLog(#"%#", [error localizedDescription]);
}
}];
}
I've tried declaring the variable like this in the .h:
#property (nonatomic) GKScore *score;
But that introduces an autosynthesised warning instead... I don't understand why this is happening when it doesn't do this in any other apps of mine?
I can't believe I did this... It shows how easy it is to miss things when you're staring at code so long...
It turns out, I have a UIImageView with the name score...
.h
IBOutlet UIImageView *score;
Simply changing the GKScore variable name, the warnings disappeared...
-(void)reportScore{
GKScore *this_score = [[GKScore alloc] initWithLeaderboardIdentifier:_leaderboardIdentifier];
this_score.value = gameScore;
[GKScore reportScores:#[this_score] withCompletionHandler:^(NSError *error) {
if (error != nil) {
NSLog(#"%#", [error localizedDescription]);
}
}];
NSLog(#"Reported to Game Center...");
}
What a doughnut!
I'm not sure what is going on.
If i report an int score from the same viewcontroller, it seems to work fine. I can send that number to the leaderboard set up in game center.
When I report an int score that is from another viewcontroller, it doesn't work. At first I thought it was because the numbers weren't in int64_t. I'm not sure if that is really the issue though.
I'm fairly new to ios programming. If this is a duplicate question, please direct me in the right direction. I really appreciate any help.
-(IBAction)report:(id)sender{
[self reportScore]; //just calling the method
}
-(void)reportScore{
GKScore *score = [[GKScore alloc] initWithLeaderboardIdentifier:_leaderboardIdentifier];
score.value = HighScore; //HighScore is the int I want from another viewcontroller.
[GKScore reportScores:#[score] withCompletionHandler:^(NSError *error) {
if (error != nil) {
NSLog(#"%#", [error localizedDescription]);
}
}];
}
I guess
GKScore *score = [[GKScore alloc] initWithLeaderboardIdentifier:_leaderboardIdentifier];
This line creating the object each time. And thats the reason you are getting the wrong result.
Try to create GKScore *score object only once which will be global and then access it.
The Game Center turn-based matchmaking interface allows a user to create a match with a number of players and fill some of those places with invites to friends and leave the others for auto-matching.
I am creating our own in-game match creation interface which works fine, so far, except when it comes to creating a match with both invited and auto-match players.
GKMatchmaker has the addPlayersToMatch method where I believe you can add auto-match players once the match exists, but GKTurnBasedMatch has no equivalent method.
The following is the code I am using, which works just fine. If anyone knows how to add a number of auto-match players it would be much appreciated!
- (GKMatchRequest *) buildMatchRequestWithFriends: (NSArray *) friendsList NumberOfPlayers: (NSInteger) numberOfPlayers
{
NSLog(#"TurnByTurnHelper.buildMatchRequestWithFriends");
GKMatchRequest *request = [[GKMatchRequest alloc] init];
NSArray *playersToInvite = [NSArray arrayWithArray:friendsList];
request.playersToInvite = playersToInvite;
request.defaultNumberOfPlayers = numberOfPlayers + 1;
return request;
}
- (void) requestMatchWithFriends:(NSArray *) friendsList NumberOfPlayers: (NSInteger) numberOfPlayers{
if (!_delegate)
{
NSLog(#"Error: Expected but did not find delegate");
return;
}
GKMatchRequest *request = [self buildMatchRequestWithFriends:friendsList NumberOfPlayers: numberOfPlayers];
[GKTurnBasedMatch findMatchForRequest: request withCompletionHandler:^(GKTurnBasedMatch *match, NSError *error)
{
if (match){
NSLog(#"findMatchForRequest: Success!");
// Add match to matches
} else {
NSLog(#"error: %#", error);
}
}];
}
Well, with a bit of searching around and testing I have discovered that the Apple
Developer documentation is incomplete and/or misleading. The following statement is made in the playersToInvite property section of GKMatchRequest:
"If the value of the property is non-nil, when you use the request to create a match, Game Center invites those players to the match. No automatching is done and the GKMatchRequest maxPlayers and minPlayers properties are ignored."
This is true for GKMatchmaker but NOT for GKTurnBasedMatch! For GKTurnBasedMatch, if you provide an array of playerIds in the playersToInvite property, the maxPlayers and minPlayers properties are NOT ignored and Game Center fills up the extra spaces with Random players.
The following code does the trick:
- (GKMatchRequest *) buildMatchRequestWithFriends: (NSArray *) friendsList NumberOfPlayers: (NSInteger) numberOfPlayers
{
GKMatchRequest *request = [[GKMatchRequest alloc] init];
NSArray *playersToInvite = [NSArray arrayWithArray:friendsList];
if([friendsList count]<=0){
request.minPlayers = 2;
request.maxPlayers = numberOfPlayers;
request.playersToInvite = nil;
} else {
request.minPlayers = 2;
request.maxPlayers = numberOfPlayers;
request.playersToInvite = playersToInvite;
}
return request;
}
And the moral of that story is: sometimes it's better not to RTFM!
Why score doesn't get incremented?
GKLeaderboard *lb = [[GKLeaderboard alloc] initWithPlayerIDs:#["G:1518137155"]];
lb.category = #"top_matcher";
[lb loadScoresWithCompletionHandler:^(NSArray *scores, NSError *error) {
if(error == nil){
GKScore *score = [scores lastObject];
if(score) {
score.value += 40;
[score reportScoreWithCompletionHandler:^(NSError *error) {
NSLog(#"ERR: %# SC:%lld %# %# %d", error, score.value, score.playerID, score.category, scores.count);
}];
}
}
}];
I see no error in output
ERR: (null) SC:61 G:1689523782 top_matcher 1
It's clearly documented here.
Almost all classes in Game Kit that send data to or retrieve information from Game Center expect the device to have an authenticated local player. The work those classes do is always on behalf of the local player. For example, if your game reports scores to a leaderboard, it can only report a score earned by the local player.
I want to implement ranking by using Game Center.
So , I implement like this .
-(void)authenticateLocalPlayer
{
GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];
localPlayer.authenticateHandler = ^(UIViewController *vc,NSError *err){
[self setLastError:err];
if ([CCDirector sharedDirector].isPaused){
[[CCDirector sharedDirector] resume];
}
if (localPlayer.authenticated){
_gameCenterFeaturesEnabled = YES;
// get localplayer's score.
GKLeaderboard *board = [[GKLeaderboard alloc] init];
// make a query
board.timeScope = GKLeaderboardTimeScopeAllTime;
// I want to get all player's score.
board.playerScope = GKLeaderboardTimeScopeToday;
// set my game category.
board.category = #"com.nobinobiru.shooting";
// I want to show top 3 score data.
board.range = NSMakeRange(1, 3);
[board loadScoresWithCompletionHandler:^(NSArray *scores, NSError *error) {
NSString *s = [NSString stringWithFormat:#"%lld",board.localPlayerScore.value];
[ud setObject:[NSString stringWithFormat:#"%#",s] forKey:#"bestScore"];
if (scores){
// I want to 3 items but it returned only 1 item.
NSLog(#"score is %#",scores);
}
}];
}else if (vc){
[[CCDirector sharedDirector] pause];
[self presentViewController:vc];
}
};
}
Then, I create 3 sandbox's user account , and I test it.
But it always only show current user's best score.
I want to show 3 sandbox's data.
I don't know why it happened like that.
My code works well in not sandbox environment?
Do you have any idea?
Thanks in advance.
All.
It works perfectly after 6 hours...
I think that the reason why it happened is my created game center account was not reflect immediately.