刚刚发现,UIDevice uniqueIdentifier属性在iOS 5中已弃用,在iOS 7及以上版本中不可用。似乎没有可供选择的方法或属性。

我们现有的许多应用程序都紧密依赖于这个属性来唯一地识别特定的设备。今后我们该如何处理这个问题?

2011-2012年的文件建议:

特殊注意事项 不要使用uniqueIdentifier属性。创建特定的唯一标识符 你可以调用CFUUIDCreate函数来创建一个UUID,然后写入 使用NSUserDefaults类将它转换到默认数据库。

但是,如果用户卸载和重新安装应用程序,这个值就不一样了。


当前回答

看起来在iOS 6中,苹果建议你使用NSUUID类。

现在UIDevice文档中的uniqueIdentifier属性的消息:

在iOS 5.0中已弃用。使用它的identifierForVendor属性 类或ASIdentifierManager的advertisingIdentifier属性 类代替,或者使用NSUUID的UUID方法 类创建UUID并将其写入用户默认数据库。

其他回答

虽然不完美,但却是UDID的最佳和最接近的替代品之一(在Swift中使用iOS 8.1和Xcode 6.1):

生成一个随机UUID

let strUUID: String = NSUUID().UUIDString

并使用KeychainWrapper库:

给keychain添加一个字符串值:

let saveSuccessful: Bool = KeychainWrapper.setString("Some String", forKey: "myKey")

从keychain中检索字符串值:

let retrievedString: String? = KeychainWrapper.stringForKey("myKey")

从keychain中删除一个字符串值:

let removeSuccessful: Bool = KeychainWrapper.removeObjectForKey("myKey")

该解决方案使用了keychain,因此存储在keychain中的记录将被持久化,即使在应用程序卸载和重新安装之后。删除该记录的唯一方法是重置设备的所有内容和设置。这就是为什么我提到这个替代方案并不完美,但仍然是iOS 8.1上使用Swift替代UDID的最佳方案之一。

如果有人在寻找替代方案时偶然发现了这个问题。我在IDManager课上就采用了这种方法, 这是不同解的集合。KeyChainUtil是一个从keychain读取的包装器。 您还可以使用散列MAC地址作为一种唯一ID。

/*  Apple confirmed this bug in their system in response to a Technical Support Incident 
    request. They said that identifierForVendor and advertisingIdentifier sometimes 
    returning all zeros can be seen both in development builds and apps downloaded over the 
    air from the App Store. They have no work around and can't say when the problem will be fixed. */
#define kBuggyASIID             @"00000000-0000-0000-0000-000000000000"

+ (NSString *) getUniqueID {
    if (NSClassFromString(@"ASIdentifierManager")) {
        NSString * asiID = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
        if ([asiID compare:kBuggyASIID] == NSOrderedSame) {
            NSLog(@"Error: This device return buggy advertisingIdentifier.");
            return [IDManager getUniqueUUID];
        } else {
            return asiID;
        }

    } else {
        return [IDManager getUniqueUUID];
    }
}


+ (NSString *) getUniqueUUID {
    NSError * error;
    NSString * uuid = [KeychainUtils getPasswordForUsername:kBuyassUser andServiceName:kIdOgBetilngService error:&error];
    if (error) {
        NSLog(@"Error geting unique UUID for this device! %@", [error localizedDescription]);
        return nil;
    }
    if (!uuid) {
        DLog(@"No UUID found. Creating a new one.");
        uuid = [IDManager GetUUID];
        uuid = [Util md5String:uuid];
        [KeychainUtils storeUsername:USER_NAME andPassword:uuid forServiceName:SERVICE_NAME updateExisting:YES error:&error];
        if (error) {
            NSLog(@"Error getting unique UUID for this device! %@", [error localizedDescription]);
            return nil;
        }
    }
    return uuid;
}

/* NSUUID is after iOS 6. */
+ (NSString *)GetUUID
{
    CFUUIDRef theUUID = CFUUIDCreate(NULL);
    CFStringRef string = CFUUIDCreateString(NULL, theUUID);
    CFRelease(theUUID);
    return [(NSString *)string autorelease];
}

#pragma mark - MAC address
// Return the local MAC addy
// Courtesy of FreeBSD hackers email list
// Last fallback for unique identifier
+ (NSString *) getMACAddress
{
    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("Error: Memory allocation error\n");
        return NULL;
    }

    if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
        printf("Error: sysctl, take 2\n");
        free(buf); // Thanks, Remy "Psy" Demerest
        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;
}

+ (NSString *) getHashedMACAddress
{
    NSString * mac = [IDManager getMACAddress];
    return [Util md5String:mac];
}

+ (NSString *)md5String:(NSString *)plainText
{
    if(plainText == nil || [plainText length] == 0)
        return nil;

    const char *value = [plainText 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]];
    }
    NSString * retString = [NSString stringWithString:outputString];
    [outputString release];
    return retString;
}

不要使用这些库——libOmnitureAppMeasurement,它使用了苹果不再支持的uniqueIdentifier

也许你可以用:

[UIDevice currentDevice].identifierForVendor.UUIDString

苹果的文档对identifierforvendor的描述如下:

对于运行在同一设备上的来自同一供应商的应用程序,此属性的值是相同的。对于同一设备上来自不同供应商的应用程序,以及不同设备上的应用程序,无论供应商如何,都会返回不同的值。

NSLog(@ % @”,[[UIDevice currentDevice] identifierForVendor]);