Save game data into iCloud via GameKit - ios

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.

Related

Firebase Auth iOS user Anonymously create but not showing in console

Suddenly this behaviour started to happen without changing anything. Basically, I'm able to create users Anonymously or even with Email/Password. I get no error whatsoever, actually I'm able to retrieve the userID. However, when I go to the users list in the console, its always empty.
Auth.auth().signInAnonymously() { user, error in
self.ifNoError(error) {
print("Signed In Anonymously \(user?.user.uid)")
}
}
Results:
Signed In Anonymously Optional("qQazZ3MX8LfQdnlz8F27QDxAT9U2")
Thank you in advance
Did you at any point delete anonymous users from the Firebase console before going live or something like that? That's what I did, not realizing that firebase keeps that user alive on your device...even if you delete the app from the device and re-install. Moreover, it will still work as an accepted anonymous user (even though deleted from the console) UNTIL you force a sign out on a given device. (Oops. TL;DR). Try this.
Sign out the user in your app delegate
FIRAuth *auth = [FIRAuth auth];
NSError *error;
[auth signOut:&error];
Create another anonymous user
[auth signInAnonymouslyWithCompletion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) {
NSLog(#"Error is %#", error);
NSLog(#"Auth result user id is %#", authResult.user.uid);
}];
In my case, my device now showed a new user UUID and that user shows up in the Firebase console.
Fun fact: This issue doesn't seem arise with Android. My Android app, which shares the same production firestore, happily created a new user after I deleted the app from the device and reinstalled.
I managed to solve the issue by creating a manual user email/password (manually on the console), sign in with it through code, delete it thorough code. Then change the code to sign in again Anonymously. This solved the problem!!

Game Center Achievement Issue

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

Detect iCloud account availibility / change using Key-Value store only?

I use iCloud Key-Value store, without any container (as I don't need documents).
So the app is not listed in Settings / iCloud / Storage / Manage Storage list, only in iCloud / iCloud Drive list, like this:
I really want to know somehow if it is turned ON or OFF, or available at all.
Seems ubiquityIdentityToken is always nil, and NSUbiquityIdentityDidChangeNotification never gets called.
I have a working prototype, modifiy a slider in simulator, it gets updated on the device, everything seems fine. Even though, if I ask for the identifiers (in the NSUbiquitousKeyValueStoreDidChangeExternallyNotification callback), they're always null:
NSURL *containerURL = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];
id token = [[NSFileManager defaultManager] ubiquityIdentityToken];
NSLog(#"containerURL: %#", containerURL);
NSLog(#"token: %#", token);
// containerURL: (null)
// token: (null)
When I turn off iCloud Drive for my app, it gets terminated in the background. No any notification gets called, nor at relaunch.
Should I simply setup a Document container I never use?
Having iCloud Documents turned on, I have the token (app entitlements get some new values as well).
But the ubiquityIdentityToken now returns value even if I turn iCloud Drive OFF (!) in device settings for the given app. It does not pulls updates from the Key-Value store, still the token is set.
Only URLForUbiquityContainerIdentifier returns nil when turned OFF, and the URL when turned ON.

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.

in app purchase "Error Domain=SKErrorDomain Code=0"

In my app I have an in-app-purchase where I allow to purchase some items. (with mkstorekit)
A think that I notice in iOS 7 is this:
if In general setting of my iPhone I'm logged with my Apple id and I proceed to purchase an item I have an error "Error Domain=SKErrorDomain Code=0" and the code finish in "canceled" block.
Then I logout from my apple id, I start again the app and when I must purchase an item it ask me id and password and its correct (naturally I insert a tester user data that I created in iTunes Connect)
At this time I stop my app and in my general setting is stored the tester user, then I start again my app and when I must purchase an item I have not the problem that I had with my personal apple id and it work fine.
In iOS 6 it didn't happen because if I was logged with my apple id in general settings and I tried to purchase an item, it showed me my apple id and asked me to insert the password (naturally it didn't work)
Finally this is not a big problem, I solve it because I used my tester account, but when I release my app in App Store can I have the same problem? If an user is logged in general setting the mkstorekit sto purchase and go in "canceled" block?
I show the method where is the cancel block:
- (void)purchaseFeature:(NSString *)productID
{
[[MKStoreManager sharedManager] buyFeature:productID
onComplete:^(NSString* purchasedFeature,
NSData* purchasedReceipt,
NSArray* availableDownloads)
{
[HUD hide:YES];
/*** CODE TO OPEN VIEW IF THE PURCHASE IS DONE ****/
}
onCancelled:^
{
NSLog(#"User Cancelled Transaction");
[HUD hide:YES];
/*** HERE FINISH MY CODE IF I'M JUST LOGGED IN GENERAL SETTING WITH MY APPLE ID ***/
}];
}

Resources