UIDevice uniqueIdentifier устарел - что теперь делать? - PullRequest
494 голосов
/ 09 августа 2011

Только что выяснилось, что свойство UIDevice uniqueIdentifier устарело в iOS 5 и недоступно в iOS 7 и выше. Похоже, что альтернативный метод или свойство недоступны или ожидаются.

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

Предложение от документации в 2011-2012 было:

Особые замечания

Не используйте свойство uniqueIdentifier. Для создания уникального идентификатора в своем приложении вы можете вызвать функцию CFUUIDCreate, чтобы создать UUID, и написать это в базу данных по умолчанию с использованием класса NSUserDefaults.

Однако это значение не будет таким, если пользователь удаляет и переустанавливает приложение.

Ответы [ 32 ]

270 голосов
/ 09 августа 2011

UUID, созданный CFUUIDCreate , является уникальным, если пользователь удаляет и переустанавливает приложение: вы будете получать новое каждый раз.

Но вы можетехотите, чтобы он был , а не уникальным, то есть он должен оставаться таким же, когда пользователь удаляет и переустанавливает приложение.Это требует немного усилий, так как наиболее надежным идентификатором для каждого устройства является MAC-адрес.Вы можете запросить MAC и использовать его в качестве UUID.

Редактировать: Конечно, всегда нужно запрашивать MAC того же интерфейса.Я думаю, что лучшая ставка на en0.MAC всегда присутствует, даже если интерфейс не имеет IP / не работает.

Редактировать 2: Как указывалось другими, предпочтительное решение, поскольку iOS 6 является - [UIDevice identifierForVendor] .В большинстве случаев вы должны иметь возможность использовать его как замену старого -[UIDevice uniqueIdentifier] (но Apple, похоже, хочет, чтобы вы использовали его, когда UUID создается при первом запуске приложения).

Редактировать 3: Таким образом, этот важный момент не теряется в шуме комментариев: не используйте MAC в качестве UUID, создайте хэш используя MAC .Этот хеш всегда будет создавать один и тот же результат каждый раз, даже при переустановках и приложениях (если хеширование выполняется одинаково).В любом случае, в настоящее время (2013 г.) в этом больше нет необходимости, кроме случаев, когда вам нужен «стабильный» идентификатор устройства на iOS <6.0. </strike>

Редактировать 4: В iOS 7,Apple теперь всегда возвращает фиксированное значение при запросе MAC, чтобы специально помешать MAC в качестве основы для схемы ID .Так что теперь вам действительно следует использовать - [UIDevice identifierForVendor] или создать UUID для каждой установки.

91 голосов
/ 22 августа 2011

Вы уже можете использовать свой вариант для Apple UDID. Добрый парень Гекиц написал категорию на UIDevice, которая сгенерирует что-то вроде UDID на основе mac-адреса устройства и идентификатора пакета.

Вы можете найти код на github

61 голосов
/ 24 октября 2011

Основываясь на ссылке, предложенной @moonlight, я провел несколько тестов, и, похоже, это лучшее решение. Как говорит @DarkDust, метод проверяет en0, который всегда доступен.
Есть 2 варианта:
uniqueDeviceIdentifier (MD5 MAC + CFBundleIdentifier) ​​
и uniqueGlobalDeviceIdentifier (MD5 от MAC), они всегда возвращают одинаковые значения.
Ниже тесты, которые я сделал (с реальным устройством):

#import "UIDevice+IdentifierAddition.h"

NSLog(@"%@",[[UIDevice currentDevice] uniqueDeviceIdentifier]);
NSLog(@"%@",[[UIDevice currentDevice] uniqueGlobalDeviceIdentifier]);

XXXX21f1f19edff198e2a2356bf4XXXX - (WIFI) UDID
XXXX7dc3c577446a2bcbd77935bdXXXX - (WIFI) GlobalAppUDID

XXXX21f1f19edff198e2a2356bf4XXXX - (3G) UDID
XXXX7dc3c577446a2bcbd77935bdXXXX - (3G) GlobalAppUDID

XXXX21f1f19edff198e2a2356bf4XXXX - (GPRS) UDID
XXXX7dc3c577446a2bcbd77935bdXXXX - (GPRS) GlobalAppUDID

XXXX21f1f19edff198e2a2356bf4XXXX - (режим AirPlane) UDID
XXXX7dc3c577446a2bcbd77935bdXXXX - (режим AirPlane) GlobalAppUDID

XXXX21f1f19edff198e2a2356bf4XXXX - (Wi-Fi) после удаления и переустановка приложения XXXX7dc3c577446a2bcbd77935bdXXXX (Wi-Fi) после удаление и установка приложения

Надеюсь, это полезно.

EDIT:
Как отмечали другие, это решение в iOS 7 больше не является полезным, поскольку uniqueIdentifier больше не доступно, а запрос MAC-адреса теперь возвращает всегда 02: 00: 00: 00: 00: 00

56 голосов
/ 06 марта 2012

проверьте это,

мы можем использовать связку ключей вместо NSUserDefaults класса, чтобы хранить UUID, созданный CFUUIDCreate.

таким способом, которого мы могли бы избежать для UUID воссоздание с переустановкой и получение всегда одного и того же UUID для одного и того же приложения, даже если пользователь удаляет и переустанавливает снова.

UUID будет воссоздан только после сброса устройства пользователем.

Я пробовал этот методс SFHFKeychainUtils , и это работает как шарм.

48 голосов
/ 20 сентября 2012

Создайте свой собственный UUID и сохраните его в связке ключей. Таким образом, оно сохраняется даже при удалении вашего приложения. Во многих случаях это также сохраняется, даже если пользователь мигрирует между устройствами (например, полное резервное копирование и восстановление на другое устройство).

По сути, он становится уникальным идентификатором пользователя . (даже лучше, чем идентификатор устройства ).

Пример:

Я определяю пользовательский метод для создания UUID как:

- (NSString *)createNewUUID 
{
    CFUUIDRef theUUID = CFUUIDCreate(NULL);
    CFStringRef string = CFUUIDCreateString(NULL, theUUID);
    CFRelease(theUUID);
    return [(NSString *)string autorelease];
}

Затем вы можете сохранить его в KEYCHAIN при первом запуске вашего приложения. Так что после первого запуска мы можем просто использовать его из цепочки для ключей, не нужно его восстанавливать. Основная причина использования Цепочки для ключей для хранения: Когда вы установите UUID в Цепочку для ключей, она будет сохраняться, даже если пользователь полностью удалит Приложение, а затем установит его снова. , Таким образом, это постоянный способ его хранения, что означает, что ключ будет уникальным во всех отношениях.

     #import "SSKeychain.h"
     #import <Security/Security.h>

При запуске приложения укажите следующий код:

 // getting the unique key (if present ) from keychain , assuming "your app identifier" as a key
       NSString *retrieveuuid = [SSKeychain passwordForService:@"your app identifier" account:@"user"];
      if (retrieveuuid == nil) { // if this is the first time app lunching , create key for device
        NSString *uuid  = [self createNewUUID];
// save newly created key to Keychain
        [SSKeychain setPassword:uuid forService:@"your app identifier" account:@"user"];
// this is the one time process
}

Загрузите файл SSKeychain.m и .h из sskeychain и перетащите файл SSKeychain.m и .h в свой проект и добавьте «Security.framework» в свой проект. Чтобы потом использовать UUID, просто наберите:

NSString *retrieveuuid = [SSKeychain passwordForService:@"your app identifier" account:@"user"];
17 голосов
/ 15 января 2013

Возможно, вы можете использовать:

[UIDevice currentDevice].identifierForVendor.UUIDString

Документация Apple описывает идентификатор ForVender следующим образом:

Значение этого свойства одинаково для приложений от одного поставщика, работающих на одном устройстве. Разное значение возвращается для приложений на одном устройстве разных производителей, а также для приложений на разных устройствах независимо от поставщика.

14 голосов
/ 28 марта 2012

Возможно, вы захотите использовать OpenUDID, который является заменой устаревшего UDID.

. В основном для соответствия UDID требуются следующие функции:

  1. уникальный или достаточно уникальный (коллизия с низкой вероятностью, вероятно, очень приемлема)
  2. постоянство при перезагрузках, восстановлении, удалении
  3. доступно в приложениях разных поставщиков (полезно для приобретения пользователейчерез сети CPI) -

OpenUDID выполняет вышеприведенное и даже имеет встроенный механизм отказа для дальнейшего рассмотрения.

Проверка http://OpenUDID.org указываетна соответствующий GitHub.Надеюсь, это поможет!

Как примечание, я бы избегал любой альтернативы MAC-адреса.Хотя MAC-адрес выглядит как заманчивое и универсальное решение, убедитесь, что этот низко висящий фрукт отравлен.MAC-адрес очень чувствителен, и Apple вполне может отказаться от доступа к нему, прежде чем вы даже скажете «ОТПРАВИТЬ ЭТО ПРИЛОЖЕНИЕ» ... сетевой адрес MAC используется для проверки подлинности определенных устройств на частных каналах (WLAN) или других виртуальных частныхсети (VPN)... это даже более чувствительно, чем прежний UDID!

11 голосов
/ 13 апреля 2012

Я уверен, что Apple раздражала многих людей этим изменением. Я разрабатываю приложение для бухгалтерии для iOS и имею онлайн-сервис для синхронизации изменений, сделанных на разных устройствах. Служба поддерживает базу данных всех устройств и изменений, которые необходимо распространить на них. Поэтому важно знать, какие устройства какие. Я слежу за устройствами, использующими UIDevice uniqueIdentifier, и за то, что оно того стоит, вот мои мысли.

  • Создать UUID и сохранить его по умолчанию? Ничего хорошего, потому что это не сохраняется, когда пользователь удаляет приложение. Если они позже установятся снова, онлайн-сервис не должен создавать новую запись устройства, что приведет к потере ресурсов на сервере и выдаче списка устройств, содержащих одно и то же, два или более раз. Пользователи увидят более одного «iPhone Боба» в списке, если переустановят приложение.

  • Создать UUID и сохранить в связке ключей? Это был мой план, поскольку он сохраняется даже при удалении приложения. Но при восстановлении резервной копии iTunes на новое устройство iOS цепочка для ключей передается, если резервная копия зашифрована. Это может привести к тому, что два устройства будут содержать один и тот же идентификатор устройства, если и старое, и новое устройства будут работать одновременно Они должны быть указаны как два устройства в онлайн-сервисе, даже если имя устройства совпадает.

  • Сгенерировать хеш MAC-адрес и идентификатор пакета? Это выглядит как лучшее решение для того, что мне нужно. Хэшируя с идентификатором пакета, созданный идентификатор устройства не позволяет отслеживать устройство по приложениям, и я получаю уникальный идентификатор для комбинации приложение + устройство.

Интересно отметить, что собственная документация Apple относится к проверке Mac квитанций App Store путем вычисления хэша системного MAC-адреса плюс идентификатор комплекта и версия. Так что это кажется допустимым политикой, независимо от того, проходит ли она проверку приложения, я пока не знаю.

11 голосов
/ 01 октября 2012

Похоже, для iOS 6 Apple рекомендует использовать класс NSUUID .

Из сообщения теперь в UIDevice документах для uniqueIdentifier:

Устаревший в iOS 5.0.Вместо этого, при необходимости, используйте свойство identifierForVendor этого класса или свойство advertisingIdentifier класса ASIdentifierManager, либо используйте метод UUID класса NSUUID для создания UUID и записи его в базу данных по умолчанию для пользователя.

11 голосов
/ 12 марта 2013

Может помочь: используйте приведенный ниже код, он всегда будет уникальным, кроме случаев, когда вы стираете (форматируете) свое устройство.

UIDevice *myDevice=[UIDevice currentDevice];
NSString *UUID = [[myDevice identifierForVendor] UUIDString];
...