Why does iOS get a new identifierForVendor when app updates?
Asked Answered
B

3

13

Every time my app is updated from the App Store some small number of the users get a new identifierForVendor for some reason. My users don't sign up or login. They are all anonymous so I need to separate them through their vendor IDs.

I've considered that there could've been insufficient space on some devices, resulting in the app being deleted and reinstalled, but that's not the case since in the last update a friend of mine had over 2GB of empty space.

I know that the identifierForVendor is changed for a user who deletes and reinstalls the app. But that's not the case here, as the app is just updated.

What could the problem be? The weird part is that this hasn't happened for development team devices yet. Or there are still users who haven't experienced this bug after countless app updates, OS updates, etc. This only happens to a small percentage of the users. All users are iOS7+ and it happens for different device models and iOS versions.

I use this code to get their ID:

static let DeviceId = UIDevice.currentDevice().identifierForVendor.UUIDString

Then I save them into NSUserDefaults:

NSUserDefaults.standardUserDefaults().setBool(true, forKey: "User" + DeviceId)
NSUserDefaults.standardUserDefaults().synchronize()

Then I check if the user exists, at every new login:

static func doesUserExist() -> Bool {
    var userDefaultValue: AnyObject? = NSUserDefaults.standardUserDefaults().valueForKey("User" + DeviceId)

    if defaultValue == true {
        println("Userdefaults already has this guy, moving on")
        FirstTime = false
        return true
    } else {
        println("First time in the app!")
        FirstTime = true
        return false
    }
}

If the user does exist it starts the login process. If the user does not exist it shows them the signup process. I am using Parse.com as backend and the deviceID is used as a username. When that small amount of users experience this bug, I see a new username and a new account created.

Befitting answered 28/5, 2015 at 15:28 Comment(6)
discussions.apple.com/thread/5114517?tstart=0 also found thisBefitting
Ever found out why it changes? I also have the same problem where people update and have a different vendor idRaskind
But but these seem like some of the possibilities I am testing atm: OS upgrades, app cache storage space, app updates, user changing itunes country, signing upto icloud or new apple serviceBefitting
Hi @Esq, did you found out what is the problem? I also have a hunch that some of our users have the identifierForVendor being changed. Thanks. Hope you see my comment. :)Gragg
No, I do not know the problem but github.com/soffes/sskeychain this helps solve itBefitting
Same isuue here,except nearly all my users vendor id changes in a update. (not all the update) Looks like a api bug since nothing about the developer info changes at all.Adiell
B
7

There was a bug affecting the calculation of identifierForVendor when updating an app from app store between May and July. Apple has claimed they have already solved the issue and pushing another update should restore the original value before the critical date. Reference: https://openradar.appspot.com/22677034

Take note that some users still have observed this issue even updating weeks after July. So it is still possible that bug is still there for some or it could resurface anytime in the future. So if you are using this data as part of your encryption, best is to save this to the keychain.

Booze answered 14/10, 2015 at 16:18 Comment(0)
F
0

Save the vendorID in the KeyChain, that will persist after deletion or any update.

-(NSString *)getUniqueDeviceIdentifierAsString
{

NSString *appName=[[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey];

NSString *strApplicationUUID = [SSKeychain passwordForService:appName account:@"incoding"];
if (strApplicationUUID == nil)
{
    strApplicationUUID  = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
    [SSKeychain setPassword:strApplicationUUID forService:appName account:@"incoding"];
}

return strApplicationUUID;
}

Disclaimer: I took the code from some other SO answer a while ago, so I don't remember whom to praise, but in the end it's not me
@Jonny found the source

Fassett answered 28/5, 2015 at 15:33 Comment(5)
thank you for the code. it will help solve this problem. however this post is focused more on what the problem might be, instead of a solution.Befitting
As mentioned in the comments to this answer: https://mcmap.net/q/169841/-how-to-preserve-identifierforvendor-in-ios-after-uninstalling-ios-app-on-device synchronization of keychain using iCloud breaks this.Compensable
@Jonny: you could solve that by adding some device information to the key. But for the question here, that is not necessary, as it's only about identifying a user - I doubt there are many users sharing their iCloud ...Fassett
If you are using the native security framework when saving to keychain, there is attribute to make a keychain item accessible only to the device. That is, it will not be synced to iTunes or iCloud. You can add to your attributes this value: CFDictionaryAddValue(attributes, kSecAttrAccessible, kSecAttrAccessibleWhenUnlockedThisDeviceOnly)Booze
I am testing in iOS11 and the same identifierForVendor is being returned after I explicitly un-install and re-install the app. I need to wait for a day to see if this persists over longer period of time. (Tested 3 un-installs and re-installs: same ID each time). Occurs both with Side-Load with Xcode managed profile, and ad-hoc builds signed with developer profile. Haven't tested yet with release-signed builds. We actually need a unique identifier for our purposes, so we will resort to using the keychain and UUID instead.Miniver
V
0

I'm confused why you're saving the IFV to NSUserDefaults first and then checking to see if that key exists. I think you should...

1) check NSUserDefaults first to see if the IFV key you created exists

2) if NSUserDefaults key does exist, great do what you need with it, this user's profile already exists

3) if key does not exist, get the IFV and save it to NSUserDefaults

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

if ([defaults valueForKey:@"IFV"]) {
    //this user already exists, do what you need to do next with IFV
}

else{
    //this is their first time using the app
    NSString *ifvString = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
    [defaults setValue:ifvString forKey:@"IFV"];

    //do what you need to do next with IFV
}
Vicariate answered 28/10, 2015 at 3:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.