Почему iOS получает новый идентификатор ForVendor при обновлении приложения?

Каждый раз, когда мое приложение обновляется из App Store, небольшое количество пользователей по какой-то причине получает новый identifierForVendor. Мои пользователи не регистрируются и не входят в систему. Все они анонимны, поэтому мне нужно разделить их по идентификаторам поставщиков.

Я подумал, что на некоторых устройствах может быть недостаточно места, в результате чего приложение будет удалено и переустановлено, но это не так, поскольку в последнем обновлении у моего друга было более 2 ГБ свободного места.

Я знаю, что identifierForVendor изменяется для пользователя, который удаляет и переустанавливает приложение. Но это не тот случай, так как приложение только что обновилось.

В чем может быть проблема? Странно то, что этого еще не произошло с устройствами команды разработчиков. Или все еще есть пользователи, которые не сталкивались с этой ошибкой после бесчисленных обновлений приложений, обновлений ОС и т. д. Это происходит только с небольшим процентом пользователей. Все пользователи iOS7+ и это происходит для разных моделей устройств и версий iOS.

Я использую этот код, чтобы получить их идентификатор:

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

Затем я сохраняю их в NSUserDefaults:

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

Затем я проверяю, существует ли пользователь при каждом новом входе в систему:

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
    }
}

Если пользователь существует, он запускает процесс входа в систему. Если пользователь не существует, он показывает им процесс регистрации. Я использую Parse.com в качестве серверной части, а идентификатор устройства используется в качестве имени пользователя. Когда это небольшое количество пользователей сталкивается с этой ошибкой, я вижу новое имя пользователя и созданную новую учетную запись.


person Esqarrouth    schedule 28.05.2015    source источник
comment
discussions.apple.com/thread/5114517?tstart=0 также нашел это   -  person Esqarrouth    schedule 28.05.2015
comment
Вы когда-нибудь узнавали, почему он меняется? У меня также есть такая же проблема, когда люди обновляются и имеют другой идентификатор поставщика.   -  person Mark Molina    schedule 05.06.2015
comment
Но это похоже на некоторые из возможностей, которые я тестирую в банкомате: обновления ОС, место для хранения кеша приложений, обновления приложений, изменение пользователем страны itunes, подписка на icloud или новый сервис Apple.   -  person Esqarrouth    schedule 05.06.2015
comment
Привет @Esq, ты выяснил, в чем проблема? У меня также есть подозрение, что у некоторых наших пользователей изменился идентификаторForVendor. Спасибо. Надеюсь, вы видите мой комментарий. :)   -  person KarenAnne    schedule 08.07.2015
comment
Нет, я не знаю, в чем проблема, но github.com/soffes/sskeychain это помогает ее решить   -  person Esqarrouth    schedule 08.07.2015
comment
То же самое здесь, за исключением почти всех изменений идентификатора поставщика моих пользователей в обновлении. (не все обновления) Похоже на ошибку API, так как ничего не меняется в информации о разработчике.   -  person MasterBeta    schedule 14.09.2015


Ответы (3)


Возникла ошибка, влияющая на вычисление идентификатораForVendor при обновлении приложения из магазина приложений в период с мая по июль. Apple заявила, что они уже решили проблему, и установка другого обновления должна восстановить исходное значение до критической даты. Ссылка: https://openradar.appspot.com/22677034

Обратите внимание, что некоторые пользователи по-прежнему наблюдают эту проблему даже через несколько недель после июля. Так что все еще возможно, что ошибка все еще существует для некоторых или может появиться снова в любое время в будущем. Поэтому, если вы используете эти данные как часть своего шифрования, лучше всего сохранить их в цепочке для ключей.

person chalcopyrite    schedule 14.10.2015

Сохраните идентификатор поставщика в цепочке ключей, который сохранится после удаления или любого обновления.

-(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;
}

Отказ от ответственности: я взял код из какого-то другого SO-ответа некоторое время назад, поэтому я не помню, кого хвалить, но, в конце концов, это не я
@Jonny нашел источник

person dogsgod    schedule 28.05.2015
comment
спасибо за код. это поможет решить эту проблему. однако этот пост больше сосредоточен на том, в чем может быть проблема, а не на ее решении. - person Esqarrouth; 28.05.2015
comment
Как упоминалось в комментариях к этому ответу: stackoverflow.com/a/21878670/129202 синхронизация цепочки для ключей с использованием iCloud нарушает это. - person Jonny; 17.06.2015
comment
@Jonny: вы можете решить эту проблему, добавив в ключ информацию об устройстве. Но для вопроса здесь это не обязательно, так как речь идет только об идентификации пользователя - я сомневаюсь, что многие пользователи делятся своим iCloud ... - person dogsgod; 17.06.2015
comment
Если вы используете собственную структуру безопасности при сохранении в цепочке для ключей, существует атрибут, позволяющий сделать элемент цепочки для ключей доступным только для устройства. То есть он не будет синхронизирован с iTunes или iCloud. Вы можете добавить к своим атрибутам это значение: CFDictionaryAddValue(attributes, kSecAttrAccessible, kSecAttrAccessibleWhenUnlockedThisDeviceOnly) - person chalcopyrite; 14.10.2015
comment
Я тестирую в iOS11, и тот же идентификаторForVendor возвращается после того, как я явно удаляю и переустанавливаю приложение. Мне нужно подождать день, чтобы увидеть, сохраняется ли это в течение более длительного периода времени. (Протестировано 3 удаления и переустановки: каждый раз один и тот же идентификатор). Происходит как с Side-Load с управляемым профилем Xcode, так и со специальными сборками, подписанными с профилем разработчика. Еще не тестировался со сборками, подписанными к выпуску. На самом деле нам нужен уникальный идентификатор для наших целей, поэтому вместо этого мы прибегнем к использованию цепочки для ключей и UUID. - person FranticRock; 27.09.2017

Я не понимаю, почему вы сначала сохраняете IFV в NSUserDefaults, а затем проверяете, существует ли этот ключ. Я думаю, тебе следует...

1) сначала проверьте NSUserDefaults, чтобы увидеть, существует ли созданный вами ключ IFV

2) если ключ NSUserDefaults существует, отлично делайте с ним то, что вам нужно, профиль этого пользователя уже существует

3) если ключ не существует, получить БМП и сохранить его в 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
}
person George Steiner    schedule 28.10.2015