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

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

2011-2012年的文件建议:

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

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


当前回答

您已经可以使用Apple UDID的替代方案了。gekitz在UIDevice上写了category,它会根据设备mac地址和包标识符生成某种UDID。

你可以在github上找到代码

其他回答

虽然不完美,但却是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的最佳方案之一。

对于Swift 3.0,请使用以下代码。

let deviceIdentifier: String = (UIDevice.current.identifierForVendor?.uuidString)!
NSLog("output is : %@", deviceIdentifier)

根据@moonlight提出的链接,我做了几次测试,这似乎是最好的解决方案。正如@DarkDust所说,该方法将检查始终可用的en0。 有两种选择: uniqueDeviceIdentifier (MAC+CFBundleIdentifier的MD5) 和uniqueGlobalDeviceIdentifier(MAC的MD5),这些总是返回相同的值。 下面是我所做的测试(用真正的设备):

#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 mode)UDID XXXX7dc3c577446a2bcbd77935bdXXXX - (AirPlane mode)GlobalAppUDID XXXX21f1f19edff198e2a2356bf4XXXX - (Wi-Fi)after removing and reinstalling the app XXXX7dc3c577446a2bcbd77935bdXXXX (Wi-Fi) after removing and installing the app

希望对大家有用。

编辑: 正如其他人指出的那样,这个解决方案在iOS 7中不再有用,因为uniqueIdentifier不再可用,查询MAC地址现在总是返回02:00:00:00:00:00

也许你可以用:

[UIDevice currentDevice].identifierForVendor.UUIDString

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

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

如果有人在寻找替代方案时偶然发现了这个问题。我在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;
}