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

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

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

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

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

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

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

Ответы [ 32 ]

7 голосов
/ 30 октября 2011

Я бы также предложил перейти с uniqueIdentifier на эту библиотеку с открытым исходным кодом (на самом деле 2 простые категории), которая использует MAC-адрес устройства вместе с идентификатором комплекта приложений для генерации уникального идентификатора в ваших приложениях.который может использоваться в качестве замены UDID.

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

Вам просто необходимо импортировать включенные NSString и UIDevice категории и вызов [[UIDevice currentDevice] uniqueDeviceIdentifier] примерно так:

#import "UIDevice+IdentifierAddition.h"
#import "NSString+MD5Addition.h"
NSString *iosFiveUDID = [[UIDevice currentDevice] uniqueDeviceIdentifier]

Вы можете найти его на Github здесь:

UIDevice с UniqueIdentifier для iOS 5


Вот категории (только файлы .m - проверьте проект github на наличие заголовков):

UIDevice + IdentifierAddition.m

#import "UIDevice+IdentifierAddition.h"
#import "NSString+MD5Addition.h"

#include <sys/socket.h> // Per msqr
#include <sys/sysctl.h>
#include <net/if.h>
#include <net/if_dl.h>

@interface UIDevice(Private)

- (NSString *) macaddress;

@end

@implementation UIDevice (IdentifierAddition)

////////////////////////////////////////////////////////////////////////////////
#pragma mark -
#pragma mark Private Methods

// Return the local MAC addy
// Courtesy of FreeBSD hackers email list
// Accidentally munged during previous update. Fixed thanks to erica sadun & mlamb.
- (NSString *) macaddress{
    
    int                 mib[6];
    size_t              len;
    char                *buf;
    unsigned char       *ptr;
    struct if_msghdr    *ifm;
    struct sockaddr_dl  *sdl;
    
    mib[0] = CTL_NET;
    mib[1] = AF_ROUTE;
    mib[2] = 0;
    mib[3] = AF_LINK;
    mib[4] = NET_RT_IFLIST;
    
    if ((mib[5] = if_nametoindex("en0")) == 0) {
        printf("Error: if_nametoindex error\n");
        return NULL;
    }
    
    if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) {
        printf("Error: sysctl, take 1\n");
        return NULL;
    }
    
    if ((buf = malloc(len)) == NULL) {
        printf("Could not allocate memory. error!\n");
        return NULL;
    }
    
    if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
        printf("Error: sysctl, take 2");
        return NULL;
    }
    
    ifm = (struct if_msghdr *)buf;
    sdl = (struct sockaddr_dl *)(ifm + 1);
    ptr = (unsigned char *)LLADDR(sdl);
    NSString *outstring = [NSString stringWithFormat:@"%02X:%02X:%02X:%02X:%02X:%02X", 
                           *ptr, *(ptr+1), *(ptr+2), *(ptr+3), *(ptr+4), *(ptr+5)];
    free(buf);
    
    return outstring;
}

////////////////////////////////////////////////////////////////////////////////
#pragma mark -
#pragma mark Public Methods

- (NSString *) uniqueDeviceIdentifier{
    NSString *macaddress = [[UIDevice currentDevice] macaddress];
    NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier];  
    NSString *stringToHash = [NSString stringWithFormat:@"%@%@",macaddress,bundleIdentifier];
    NSString *uniqueIdentifier = [stringToHash stringFromMD5];  
    return uniqueIdentifier;
}

- (NSString *) uniqueGlobalDeviceIdentifier{
    NSString *macaddress = [[UIDevice currentDevice] macaddress];
    NSString *uniqueIdentifier = [macaddress stringFromMD5];    
    return uniqueIdentifier;
}

@end

NSString + MD5Addition.m:

#import "NSString+MD5Addition.h"
#import <CommonCrypto/CommonDigest.h>

@implementation NSString(MD5Addition)

- (NSString *) stringFromMD5{
    
    if(self == nil || [self length] == 0)
        return nil;
    
    const char *value = [self UTF8String];
    
    unsigned char outputBuffer[CC_MD5_DIGEST_LENGTH];
    CC_MD5(value, strlen(value), outputBuffer);
    
    NSMutableString *outputString = [[NSMutableString alloc] initWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
    for(NSInteger count = 0; count < CC_MD5_DIGEST_LENGTH; count++){
        [outputString appendFormat:@"%02x",outputBuffer[count]];
    }
    return [outputString autorelease];
}

@end
5 голосов
/ 31 октября 2012

Вы можете получить из этого кода: UIDevice-with-UniqueIdentifier-для-iOS-5

4 голосов
/ 10 августа 2011

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

После некоторых дальнейших исследований мне кажется, что мы остались без надлежащегоальтернатива на данный момент.Я серьезно надеюсь, что Apple пересмотрит их решение.

Может быть, было бы неплохо написать Apple по этой теме и / или подать запрос об ошибке / функции, так как, возможно, они даже не знают о полных последствияхдля разработчиков.

4 голосов
/ 08 апреля 2013

UIDevice identifierForVendor представленный в iOS 6 будет работать для ваших целей.

identifierForVendor - буквенно-цифровая строка, которая однозначно идентифицирует устройство для поставщика приложения. (Только для чтения)

@property(nonatomic, readonly, retain) NSUUID *identifierForVendor

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

Доступно в iOS 6.0 и более поздних версиях и объявлено в UIDevice.h

Для iOS 5 см. Эту ссылку UIDevice-with-UniqueIdentifier-для-iOS-5

4 голосов
/ 04 сентября 2013

Использование SSKeychain и кода, упомянутого выше.Вот код для копирования / вставки (добавьте модуль SSKeychain):

+(NSString *) getUUID {

//Use the bundle name as the App identifier. No need to get the localized version.

NSString *Appname = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"];    

//Check if we have UUID already

NSString *retrieveuuid = [SSKeychain passwordForService:Appname account:@"user"];

if (retrieveuuid == NULL)
{

    //Create new key for this app/device

    CFUUIDRef newUniqueId = CFUUIDCreate(kCFAllocatorDefault);

    retrieveuuid = (__bridge_transfer NSString*)CFUUIDCreateString(kCFAllocatorDefault, newUniqueId);

    CFRelease(newUniqueId);

    //Save key to Keychain
    [SSKeychain setPassword:retrieveuuid forService:Appname account:@"user"];
}

return retrieveuuid;

}

3 голосов
/ 09 августа 2013

Следующий код помогает получить UDID:

        udid = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
        NSLog(@"UDID : %@", udid);
3 голосов
/ 17 сентября 2013

Это код, который я использую для получения идентификатора для iOS 5 и iOS 6, 7:

- (NSString *) advertisingIdentifier
{
    if (!NSClassFromString(@"ASIdentifierManager")) {
        SEL selector = NSSelectorFromString(@"uniqueIdentifier");
        if ([[UIDevice currentDevice] respondsToSelector:selector]) {
            return [[UIDevice currentDevice] performSelector:selector];
        }
    }
    return [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
}
2 голосов
/ 21 июня 2017

iOS 11 представила инфраструктуру DeviceCheck. Имеет полностью защищенное решение для уникальной идентификации устройства.

2 голосов
/ 17 октября 2012

Начиная с iOS 6, у нас есть NSUUID класс, который соответствует RFC4122

Apple Link: apple_ref для NSUUID

1 голос
/ 24 августа 2017

Apple добавила в iOS 11 новый фреймворк под названием DeviceCheck, который поможет вам очень легко получить уникальный идентификатор. Прочитайте эту форму больше информации. https://medium.com/@santoshbotre01/unique-identifier-for-the-ios-devices-590bb778290d

...