Using the Game Center player identifier in a parse PFUser object? - ios

I want to use Apples Game Center for players to log in to my game, but I also want to store additional gameplay related data from the players as well. I want to use the Parse.com service, so I was thinking about having the players signup/login to Game Center when the game loads, and then if it's not already been done, store the players, "player identifier" in a PFUser object on parse. That way I'll be able to store data for the player on parse.
So my question (finally) is, is that a good way to do it? I'm new to iOS so I was wondering if there are any obvious issues with that way of doing things that I'm missing?
Thanks for any advice.

It's not a bad way to do it. That way you use a unique ID for each parse user, then storing additional data in Parse is easy. The steps would be:
authenticate the user with GameCenter
login to Parse with an auto ID or username/password combination
set a new 'gameCenter ID' property for your PFUser in Parse
You'll face some data redundancy, though it's worth noting that the PFUser uniqueID is created on the server side and can't be seeded or modified on the device (not even after creation, I believe). Adding a separate field to your user database to store the GKID data will allow you to find & allocate data to a specific user in the future.
Here's the relevant page from Apple's GameCenter Documentation
Also worth noting: you can generate a PFUser with an auto ID (assuming your user has internet connectivity), which will be as useful for you when saving additional data, so you may not even need to use the GameCenter userID. This auto ID will likely persist within the app until the user a) updates the app, b) deletes and reinstalls the app, or c) follows any other login/signup process you have in the app (Parse is your friend). The primary reason for using the GameCenter ID is that it will be the same for a user across devices/app installs/updates, etc.

Related

What is considered too heavy for UserDefaults?

I'm building a simple iOS app that will be the first I'll have put on Apple's App Store. At one point, the app accesses the user's contact list and lets them select any number of contacts they want to save as favorites.
For ease of building version one, I am currently using UserDefaults to save these favorites. While it has worked well in my limited testing, I know that Core Data and CloudKit are stable options for larger solutions.
For an app like mine, where I'm only using UserDefaults to save a select number of contacts as favorites, is UserDefaults an adequate solution? Or should I transition to something more robust like Core Data or CloudKit? There is no limit on the number of contacts a user could select as a favorite, so there is the edge-case possibility of a user selecting all of their contacts one by one and attempting to save them all as favorites.
If the user gets a new phone and loses all existing data due to UserDefaults being local on the device, it would not take long to get this app back to where they previously had it.
You can use CoreData to store favorite contact locally for large data as per your concern. Now when user switch device or delete app then all data will removed. So for that you can sync with cloudKit or other option is backend server. When user add any contact as favourite same time that contact will add to Core data as well as in backend server. You can sync this backend server data when user login first time in the app, then you no need to sync again. other all thing are as per requirement.

Using Database in an IOS Appp

This may seem like a typical google question but after spending an hour reading various stuff, I am way more confused than I hoped to be.
I am in the middle of developing a game and I have a bunch of data, which is better off being stored inside a database (information regarding monsters such as level sprites ect). Now I also want to have in app purchases later and from what I read firebase is a good way to store inapp purchase information (which user has acquired what, highscore ect.).
Please correct me if I am wrong: All the informations regarding monsters ect. should also be stored inside a database, best case inbuilt app database. For that I planned to use sqllite or core data. I assume that since firebase is cloud based, it is not smart to load data from there just to start a game as a user would always have to be connected to it. (again please correct if wrong)
Anyways I plan to use sqllite or core data to store game information inside the app so that no user can modify it. For data such as high score in app purchases ect. I plan to use firebase.
So my question would be am I on the right track or is everything I said rubbish and there is a better way...
Help is appreciated thank you very much.
For the In app purchase I recommend using this library: https://github.com/kishikawakatsumi/KeychainAccess
The data will not get lost even if a user deletes your app and then downloads it again. It is handy to store buying info in keychain access, since a user won´t need to click the restore purchase button to get what he has bought before (if he deletes the app at some point).
import KeychainAccess
let keychain = Keychain(service: "com.myservice.myapp")
//when a user buys call this:
self.keychain["hasBoughtAcceess"] = "yes"
//to check if user has bought:
if(self.keychain["hasBoughtAccess"] == "yes") {
print("user has bought")
}
else {
print("user has not bought")
}

iCloud GUID Across Devices

I'm trying to figure out a way to generate a unique iCloud ID that will be the same across devices. My app stores data in an online database that I would like to tie back to an iCloud id. This gives the nice user experience of not having to deal with logins (since all data is tied to their iCloud account), without being stuck using iCloud's lousy sync. The problem is that as far as I know, there's no API that will give me this kind of ID.
Things I've tried/thought about:
1) NSUbiquitousKeyValueStore
Doesn't work, because the value will get updated "sometime later" i.e. - whenever Apple feels like it.
2) iCloud Document Storage
Same problem as #1, with the added bonus of storing a random file in the device that the user can remove by hand
3) Using [[NSFileManager defaultManager] ubiquityIdentityToken]
Because the Ubiquity Token's bytes are the same for any given login session, I imagined it may be that this may be the case across devices. Not the case
4) Using the Address Book Contact
Seems like it would be unreliable (what happens if they change their main email/phone number/name), plus has the side effect of annoying/freaking out the user at first launch (how do they know I'm not stealing all their contacts?)
5) Rolling my own login system tied to a remote server
This seems to be the only option available, although I'd prefer a better one.
Thanks in advance
Perhaps this is too late to be useful, but iOS 8 has provided a solution here. From the WWDC 2014 “Intro to CloudKit” session:
So, instead what we do is on a container by container basis we come up with a random ID. This is an identifier that is stable so that is your application no matter what client it's running on talking to this container will get the same identifier, but it's not identifying the user via any personal information. … We've given you enough support that if you wanted to you could implement a login via iCloud flow in your application using the CloudKit framework.
[ Transcription courtesy of http://asciiwwdc.com/2014/sessions/208 ]
To flesh that out a bit more, if your app is provisioned for CloudKit storage then its default container comes with an auto-generated user record representing the currently signed-in iCloud user (if any). The UUID (actually called recordName) associated with this user record is consistent for your app across installs and across devices.
E.g.:
[[CKContainer defaultContainer] fetchUserRecordIDWithCompletionHandler:^(CKRecordID *recordID, NSError *error) {
…
myiCloudUserID = recordID.recordName;
}];
There is no persistent unique identifier for iCloud.
Option 5 is your best bet unless you want to do conflict resolution on a sync'd file that uses document storage.

Good Practice to save game center data (GKTurnBasedMatch)?

I am making a game app with game center.
I would like to ask what is the good practice for saving game data like whole object (GKTurnBasedMatch) in app?
Since, there is matchData for each of the match. I am planning to save this GKTurnBasedMatch in NSDefault , however no luck for retrieving it from the nsdefault. So, is there any good way to do so ?
Could you guys please give me some advises? my consideration is only what if i update the app , would NSDefault data be deleted after the app update?
It's not good practice to store these objects at all. The "truth" for Game Kit is at Game Center, so your app should be retrieving the latest information from Game Center to ensure everything's up to date. Imagine if your user has two different devices, and makes progress on a game on one device; if the other device is relying on shared state then it would miss out on the updates.
When your app launches, use +[GKTurnBasedMatch loadMatchesWithCompletionHandler:] to find out what matches are currently in progress. If you need to store custom data with the matches, store it in the matchData property on the match so that it's synced with Game Center.
If you want to support some kind of limited offline display, I'd take the properties you need to be able to show and store those associated with the match ID (so you can match it back to a live match when you get reconnected to Game Center. For example, you could store the match participants' names and the current message. Those are all just strings, so you could easily them with the match ID in user defaults.

iOS: can game center account somehow be used for authentication on custom webservice?

Let's say we wan to have a custom backend for a iOS game that manages user accounts and allows the users to send objects to each other, but we don't want to actually have the user to create a dedicated useraccount for our game. It would be possible to simply use the playerID for the usermanagement, but that would not be secure. Is there any way to use a local gamecenter authentication to also authenticate at a custom webservice?
Currently i ponder about how the game 'pocket frogs' enables the players to send gifts to gamecenter friends. Gamecenter doesn't seem to provide this functionality so i assume they use a custom backend for it, but how can such a backend authenticate the player?
I can't say for sure if this is how Pocket Frogs (PF) does it, but based on the fact that only Game Center (GC) friends who also play PF appear on the neighbours list, I think it may work like this:
When a player first starts the game, they get a user id (a 32-bit int, say) from the PF back end which is stored locally. Once the player has this id it can be stored in one of the GC leaderboards under the GKScore context property rather than the value. As far as I can see, PF automatically adds every player to all of the leaderboards pretty much straight away.
Then when another player wants to send a gift, PF gets the leaderboard scores for all of their GC friends and if they have a valid score they must be a PF player and the context value can be read to get their PF id.
In this way the PF back end gets the correct id, but doesn't need to use their GC id.
Incidentally, I tried out the idea of using challenges for sending gifts, and it can work. See http://www.lrgdigital.com/ofgame.html for the game I tried it with - you have to win a game before you can gift it. It has the benefit that you can send the gift to anyone on your friends list rather than only friends who play the game, but there are some limitations as well.
No. Gamecenter uses apple id and that is off limits for obvious reasons. And if you look into the game center framework, there is a way to get gamecenter friends.
Look here to see how to get an array of friends: Game Center Friend List

Resources