Tertium Tertium - 4 months ago 8
iOS Question

User id in iOS to store profiles and check IAP

My app has in-app currency and non-consumable products, it stores user profiles and posts values to leaderboards on my server.

In Android (pure java) I have LVL user ID - it is unique for pair developer-customer, so I easily manage user profiles on all his devices, and I can distinguish between devices using IMEI or Android ID.

In Windows/Windows Phone (monogame) I have LiveID, but devices have no id except self-generated UUID for statistics/ads. Can't be sure it persists reinstalls and updates.

And what about iOS (and maybe OSX) (Xamarin.iOS/monogame)?
As far as I remember in iOS was device id, but then api was deprecated.
What do you use as device/user id?
Maybe there is some user-unique-id that StoreKit has behind the scenes?
Or something related to cloud id, to distinguish users, not devices?
If none is available - is there a way to keep random UUID persistent on device, even if user reinstalls app?


When Apple removed the UUID, they provided the identifierForVendor method (In UIDevice) to replace it. It provides a UUID that is unique for you (the developer) for a particular device. I can't tell you how to call that from xamarin, but would assume it's possible.

If you want something that will persist across app deletes you could create your own UUID and save it to the keychain. You can use app groups to have a shared keychain for all of your apps, and keychain entries DO persist if you delete and reinstall an app.

Tertium: Here is the example code (tested). If you store it in cloud you can use it on all user's devices.

        void SaveValueToKeychain(string key, String value)
            var s = new SecRecord(SecKind.GenericPassword)
                ValueData = NSData.FromString(value),
                Generic = NSData.FromString(key),
                Invisible = true,
                CreationDate = NSDate.Now

            var err = SecKeyChain.Add(s);


        public String GetValueFromKeychain(string key)
            String ret = null;
            SecStatusCode res;
            var rec = new SecRecord(SecKind.GenericPassword)
                Generic = NSData.FromString(key)
            var match = SecKeyChain.QueryAsRecord(rec, out res);
            if (match != null)
                ret = match.ValueData.ToString();
            return ret;


        string UUID_KEY = "com.my.app";
        String id = GetValueFromKeychain(UUID_KEY);

        if (id == null)
            Guid g = Guid.NewGuid();
            String gs = g.ToString().Replace("-", "");
            Debug.Write("ID not found, generating: " + gs);
            SaveValueToKeychain(UUID_KEY, gs);
            id = GetValueFromKeychain(UUID_KEY);
            Debug.Write("ID found: " + id);