Game Center Achievement Issue - ios

I have recently decided to add achievements to a game that has been on the App Store for years now, and I'm having issues with making them work.
I am using the following code to post the achievements:
GKAchievement *achievement = [[GKAchievement alloc] initWithIdentifier: identifier];
[achievement setPercentComplete:100.0];
[GKAchievement reportAchievements:#[achievement] withCompletionHandler:^(NSError *error){
}];
But reportAchievements just logs no bundle for bundleID: (null).
I'm wondering if it has something to do with the fact that achievements aren't live yet and Apple has removed sandbox servers. But they are registered in iTunes Connect and I'm using a Test User.
It is also important to note that this app was transferred from a different developer.
For the app ID I tried using:
com.olddeveloper.ach_id
com.olddeveloper.appid.ach_id
ach_id
com.newdeveloper.ach_id
com.newdeveloper.appid.ach_id
The leaderboard that has been present since before the transfer is still working and it uses the old developer's ID.
I even tried just getting a list of all achievements using the code in the first answer here, but it still says no bundle for bundleID: (null).
EDIT:
I found that even though it says no bundle for bundleID: (null), it still correctly returns a list of all achievements. I assume that this message is just some glitch in the system and that it works anyway.
That said, I am still unable to make achievements unlock using any combination of ID.

For me the problem was that the achievement was being unlocked, but not displaying. I don't know of any way to not display the message, but it is harmless.

I faced the same issue. Stepping cautiously through my code in my debugger, I came to figure out if I use GKScore instead of GKAchievement , the warning message disappears.
So thumb rule is check your achievements and leaderboards. Go with GKScore instead of GKAchievement.
[ GKAchievement reportAchievements:achievements withCompletionHandler:^(NSError *error) {
if ( error != 0 )
NSLog( #"Reporting of %# failed: %#", achievement, [ error localizedDescription ] );
}];
You can also see the radar. It is with no. rdar://23149890

I received the same error message while accidentally trying to report an achievement within my app that was not configured in iTunes Connect.
So, the following steps might help you:
Check iTunes Connect for missing achievements
Check your achievement ids for spelling mistakes

Related

Parse Log in With Twitter Initial Failure

Currently I have a Twitter login that authenticates the user just fine, receiving all the appropriate information for the user necessary for confirming a complete login.
I then am calling the [PFTwitterUtils logInWithBlock:...] method in order to authenticate the user through Parse and populate a new user in _User.
(I am not using just this method to present the Twitter login dialog box as I could not get it to present itself).
Here is the strange part:
On the first time I launch the app, I sign in with Twitter, and then call the logInWithBlock method and receive the following error:
Something went wrong: The operation couldn’t be completed. (NSURLErrorDomain error -1012.)
The strange part is that this issue does not occur at all if I relaunch the app again. The only difference is that upon relaunch I believe the Twitter Account information that I had used before (via browser not accounts) is saved on the device. When I launch the app again, I have it set so that it reloads the previous session: this time the [PFTwitterUtils logInWithBlock:...] works like a charm, creates a new user, etc., without any issue.
NOTE: I have a valid URL saved as the Callback URL on my Twitter App's settings. Also, I hope it is clear that the setup was done correctly given that it works fine on second log in.
Here is the login code I am using:
// Login with Twitter through Parse
[PFTwitterUtils logInWithBlock:^(PFUser *user, NSError *error) {
if (error != nil) {
// Something went wrong
NSLog(#"Something went wrong: %#", [error localizedDescription]);
breakLogin = YES;
[self invalidateSignInTimer];
return;
}
else if (user.isNew){
userObjectID = user.objectId;
[user saveInBackground];
NSLog(#"New User");
}
else if (!user.isNew) {
userObjectID = user.objectId;
[user saveInBackground];
NSLog(#"Returning User. Welcome Back!");
}
}];
I am running out of patience and ideas on why this is happening. If anyone has any ideas please let me know - thanks!
UPDATE:
I noticed that the reason this seems to be happening is such:
The first time i attempt to login there is no PFUser, whereas the second time there seems to be a saved [PFUser currentUser], which allows the [PFTwitterUtils...] method to log in and create the new user.
Yet I am still not sure how to prevent the failure the first time without manually creating a new PFUser and then logging in with Twitter, then PFTwitterUtils...
UPDATE 2
I have resolved this issue with the answer I have provided below. I am leaving this up as I feel this is something that may help others out there in the future.
So after extraneous research, I seemed to have found a solution.
First I made sure that all of my framework files (SKDs, headers, etc) were up to date by removing all of their references from both the project and the library linking.
Second I made sure that all keys and secrets were remade and updated in my
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
Lastly I made double checked that I properly went through the set up for Twitter authentication through Parse's website.
BUT what I found to be the only solution rested in the Callback URL.
When specifying the Callback URL in your Twitter Application under "Settings", I had to uncheck the Lock Callback URL option, despite the recommendation by Twitter. (seen below)
I was a little unhappy that all of this trouble derived from something so mundane, however I was at least pleased that solution was in fact resolved without too much trouble. Hopefully this answer helps someone out there struggling with a similar issue.

can't saveGameData because "not signed in to iCloud" although I am signed

I get the error:
Error Domain=GKErrorDomain Code=27 "The requested operation could not be completed because you are not signed in to iCloud" UserInfo=0x1889f160 {NSLocalizedDescription=The requested operation could not be completed because you are not signed in to iCloud}
when I'm trying to save game data using this obvious code:
[[GKLocalPlayer localPlayer] saveGameData:serializedData withName:#"SaveName" completionHandler:^(GKSavedGame *savedGame, NSError *error) {
if (savedGame != nil) {
NSLog(#"Player data saved to GameCenter: %#", savedGame);
} else {
NSLog(#"Player data NOT saved to GameCenter, error: %#", error.description);
}
}];
It's even more strange because it worked two weeks ago, so I commented it out and started coding other stuff: leaderboards, in-app purchase – and all these work.
I'm testing it on my iPhone (iOS 8.1.3) logged to Game Center, to iCloud, I've got iCloud Drive turned on, but saving doesn't work. I even set up a new test account, but with the same result.
Could testing all these functionalities on same test account make this problem or it's time to contact Apple?
I´ve had the same problem.
try to log into icloud with your standard account(not TestUser).
activate iCloud > iCloud Documents in Capabilities. Turn ON iCloud Drive in Phone Settings (Device) and it should work.
Had the same problem. I did add iCloud Capabilities, but only in ReleaseForProfiling mistakenly. I should do it in ALL sections.

Save game data into iCloud via GameKit

I'm trying to save game's data to iCloud via next code:
GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];
[localPlayer saveGameData:[NSData dataWithBytes:rawData->data() length:rawData->size()]
withName:[NSString stringWithUTF8String:fileName.c_str()]
completionHandler:^(GKSavedGame *savedGame, NSError *error) {
if (error == nil) {
DebugLog(#"Snapshot successfully saved");
} else {
DebugLog(#"saveSnapshot error: %#", error.description);
}
}];
But getting error message: The requested operation could not be completed because you are not signed in to iCloud
I've tried to do this in iOS Simulator and on device but didn't succeed.
And tried to use test apple ID, dev apple ID, new apple ID, but didn't succeed too.
User is logged in to iCloud in iOS Settings and logged in to Game Center.
Any suggestions?
I had a similar issue. After I signed in with my iCloud account on my device's settings, the exact same error was still showing up, and it only stopped when I enabled the iCloud Drive for my account, otherwise it will never work.
So, it looks like the user must be using iCloud Drive, otherwise GKSavedGame will never work. Apple docs never mention that as far as I'm aware.
Prerequisite:
You must have an Apple ID.
Check you have your Capabilities set.
Capabilities > iCloud > ON
(You must have iCloud Documents checked.)
Capabilities > Game Center > ON
Go to iCloud and create your account
From your computer browser, just login with your Apple ID and accept the terms and conditions. Like here: https://www.icloud.com/#settings
Now you can log in with your device or simulator, in Settings > iCloud.

GKTurnBasedMatch Network Issues

I've been trying to implement a way to notice when my app gets disconnected from Game Center since ending a turn while disconnected breaks the app. I just started testing on my iPad with the WiFi off and noticed that even when I completely quit the app, it automatically authenticates my player and signs me into game center. It even loads game data from recent games. I then tried going on the game center app itself and the only thing that caused a network error was clicking on the "Games" tab. Obviously much of the data is being cached so I don't know what to check to see if I'm disconnected.
So how can I test if the device is connected to Game Center? Neither Match data, participants, nor any of their properties are nil, and the player is always authenticated.
Try to manage this with two things :
Network connection : with something like FXReachability and then [FXReachability isReachable]
Game Center authentification :
In your app test authentification with :
GKLocalPlayer.localPlayer.isAuthenticated
More generally, always test completion handlers errors and array existence like this :
[GKTurnBasedMatch loadMatchesWithCompletionHandler:^(NSArray *matches, NSError *error) {
if (error) {
// what kind of error ?
}
if (matches) {
// do what you need to do
}}];
Hope this will help you a little bit...

iOS SFHFKeychainUtils failing *sometimes* with error -25308 errSecInteractionNotAllowed

I have this code getting back a password from the keychain for a given username NSString:
NSError *error = nil;
NSString *appName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey];
NSString *pw = [SFHFKeychainUtils getPasswordForUsername:username andServiceName:appName error:&error];
if(error != nil)
// log the error
Most of the time for most users this all works fine - but for some specific users this call seems to fail (and carry on failing) where it returns the following error:
The operation couldn’t be completed. (SFHFKeychainUtilsErrorDomain error -25308.)
This is apparently errSecInteractionNotAllowed - which from what I've read I think this means some kind of user interaction is required for the keychain to be accessed.
Does anyone have any idea why this call may be failing for some specific users only? This keychain entry is specific to my app - so why would any user interaction be required to access it?
Any pointers much appreciated...
OK so I worked this out finally.
Eventually I worked out the users who were having problems had set a lock code on their phone. If the phone was locked the keychain system was returning this -25308 error.
If you only ever need to access the keychain when the app is active in the forground you would never see this issue - but if you need to carry on processing when the phone is locked or if the app is in background then you would see it.
Elsewhere I'd read that the default access attribute for the kechain system is kSecAttrAccessibleAlways - but I think that is out of date. It seems the default access attribute for the keychain system is such that when the phone is locked with a pin code then the items are unavailable.
The fix for this is to change the SFHFKeychainUtils code to set a specific kSecAttrAccessible attribute on the keychain items it manages (which the original code did not do - presumably as it pre-dated these attributes).
This wordpress updated version of the SFHFKeychainUtils code has the fixes in it - search for kSecAttrAccessible to see where they have added the accessible attribute code.
Hope this helps anyone else running into this...
I was having this issue in iOS 14 with Widgets extensions that are accessing to the keychain to get the JWT token to call some rests.
Apparently, widgets tried by default to update also when the device is locked and the keychain item I was trying to use was not accessible.
After setting this attribute to the keychain element (swift 5 code), everything seems to be working:
keychainItem[kSecAttrAccessible as String] = kSecAttrAccessibleAfterFirstUnlock

Resources