UIDevice uniqueIdentifier已弃用-现在要做什么?

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

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

2011-2012年的文件的建议是:

特殊注意事项

不要使用uniqueIdentifier属性。创建特定的唯一标识符 到你的应用程序,你可以调用CFUUIDCreate函数来创建一个UUID,并写入 使用NSUserDefaults类将它转换为默认数据库

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

164982 次浏览

如果用户卸载并重新安装应用程序,则由CFUUIDCreate 创建的UUID是唯一的:你每次都会得到一个新的UUID。

但是你可能希望它是唯一的,也就是说,当用户卸载和重新安装应用程序时,它应该保持不变。这需要一些努力,因为最可靠的每个设备标识符似乎是MAC地址。你可以查询MAC并使用它作为UUID。

编辑:当然,总是需要查询同一接口的MAC。我想最好的办法是用en0。MAC一直在位,即使接口没有IP/is down .使用实例

正如其他人所指出的,自iOS 6以来的首选解决方案是- - - - - - [UIDevice identifierForVendor]。在大多数情况下,你应该能够使用它作为旧的-[UIDevice uniqueIdentifier]的替换(但是当应用程序第一次启动时创建的UUID似乎是Apple希望你使用的)。

因此,这一点不会在注释噪声中丢失:不要使用MAC作为UUID,使用MAC创建一个哈希。哈希每次都会创建相同的结果,即使是在重新安装和应用程序之间(如果哈希以相同的方式完成)。不管怎样,现在(2013年)这已经没有必要了,除非你在iOS <上需要一个“稳定的”设备标识符;6.0.

编辑4:在iOS 7中,Apple现在在查询MAC时总是返回一个固定值,以专门阻止MAC作为ID的基础方案。所以你现在真的应该使用- - - - - - [UIDevice identifierForVendor]或创建一个每安装UUID。

MAC地址可以被欺骗,这使得这种方法对于将内容绑定到特定用户或实现黑名单等安全功能毫无用处。

经过一些进一步的研究,在我看来,我们现在没有一个合适的替代方案。我真心希望苹果能重新考虑他们的决定。

也许给苹果发邮件讨论这个话题是个好主意,或者提交一个关于这个问题的bug /功能请求,因为他们可能还没有意识到这对开发者的全部后果。

你已经可以使用Apple UDID的替代品了。好心的家伙gekitz在UIDevice上写了category,它将根据设备mac地址和包标识符生成某种UDID

你可以在github上找到代码

根据@moonlight提出的链接,我做了几次测试,这似乎是最好的解决方案。正如@DarkDust所说,该方法将检查en0,它总是可用的 有两个选项:
uniqueDeviceIdentifier (MD5 of MAC+CFBundleIdentifier)
.使用实例 和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 -(飞机模式)UDID
XXXX7dc3c577446a2bcbd77935bdXXXX - (AirPlane mode)GlobalAppUDID

.(飞机模式

XXXX21f1f19edff198e2a2356bf4XXXX - (Wi-Fi)后删除和 重新安装应用程序XXXX7dc3c577446a2bcbd77935bdXXXX (Wi-Fi)后 删除和安装应用

希望对大家有用。

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

我还建议从uniqueIdentifier改为这个开源库(2个简单的类别),利用设备的MAC地址和应用程序包标识符在应用程序中生成一个唯一的ID,可以用作UDID替换。

请记住,与UDID不同,这个数字对每个应用程序都是不同的。

你只需要导入包含的NSStringUIDevice类别,并像这样调用[[UIDevice currentDevice] uniqueDeviceIdentifier]:

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

你可以在Github上找到它:

UIDevice with UniqueIdentifier for 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

看看这个,

我们可以使用Keychain代替NSUserDefaults类,来存储由CFUUIDCreate创建的UUID

这样我们可以避免UUID重新安装, 并且对于相同的应用程序,即使用户卸载并重新安装,也始终获得相同的UUID

UUID将在用户重置设备时重新创建。

我用SFHFKeychainUtils尝试了这个方法,它的工作就像一个魅力。

你可能想要考虑使用OpenUDID,它是已弃用的UDID的替代品。

基本上,要匹配UDID,需要以下特性:

  1. 唯一或足够唯一(低概率碰撞为 可能非常可以接受)
  2. 跨重启、恢复、卸载的持久性
  3. 在不同供应商的应用程序中可用(通过CPI网络获取用户很有用)-

OpenUDID实现了上述功能,甚至有一个内置的选择退出机制供以后考虑。

检查http://OpenUDID.org它指向相应的GitHub。 希望这能有所帮助!< / p >

作为旁注,我将回避任何MAC地址的替代方案。虽然MAC地址似乎是一种诱人的通用解决方案,但要确保这个唾手可得的果实是有毒的。MAC地址是非常敏感的,在你说“提交这个应用程序”之前,苹果可能会非常反对访问这个地址……MAC网络地址用于对wlan (private lan)或其他vpn (virtual private network)中的某些设备进行认证。它甚至比以前的UDID更敏感!

我相信苹果公司的这一变化惹恼了很多人。我为iOS开发了记账软件,并有一个在线服务来同步在不同设备上所做的更改。该服务维护所有设备的数据库以及需要传播到这些设备的更改。因此,了解哪种设备是哪种设备很重要。我使用UIDevice uniqueIdentifier跟踪设备,为了它的价值,这里是我的想法。

  • 生成UUID并存储在用户默认值中? 没有好处,因为当用户删除应用程序时,这不会持续存在。如果他们稍后再次安装,在线服务不应该创建新的设备记录,这将浪费服务器上的资源,并给出包含相同设备两次或两次以上的设备列表。如果用户重新安装应用,他们会看到不止一个“Bob’s iPhone”

  • 生成UUID并存储在keychain中? 这是我的计划,因为它仍然存在,即使应用程序卸载。但在将iTunes备份恢复到新的iOS设备时,如果备份是加密的,则会传输密钥链。这可能导致两个设备包含相同的设备id,如果旧设备和新设备都在服务中。在联机服务中,即使设备名称相同,这些设备也应该被列为两台设备

  • 生成MAC地址和bundle id的散列? 这似乎是我需要的最佳解决方案。通过与bundle id进行哈希,生成的设备id不会使设备在应用程序中被跟踪,我得到了应用程序+设备组合的唯一id

有趣的是,苹果自己的文档引用了通过计算系统MAC地址加上bundle id和版本的哈希来验证Mac应用商店收据。所以这似乎是政策允许的,但是否通过应用审查我还不知道。

创建自己的UUID,然后将其存储在Keychain中。因此,即使你的应用程序被卸载,它仍然存在。在许多情况下,即使用户在设备之间迁移(例如完全备份并恢复到另一个设备),它也会持续存在。

实际上,就你所关心的而言,它变成了唯一的用户标识符。(甚至比设备标识符更好)。

例子:

我定义了一个自定义方法来创建UUID:

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

然后,你可以在你的应用程序第一次启动时将它存储在KEYCHAIN中。因此,在第一次启动后,我们可以简单地从keychain中使用它,不需要重新生成它。使用Keychain存储的主要原因是:当你将UUID设置为Keychain时,即使用户完全卸载了应用程序,然后重新安装它,它也会持续存在。这是存储它的永久方式,这意味着键会一直是唯一的。

     #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
}
< p > SSKeychain下载。m和.h文件从sskeychain和拖动SSKeychain。m和.h文件到你的项目,并添加“Security.framework”到你的项目。 之后使用UUID只需使用:

NSString *retrieveuuid = [SSKeychain passwordForService:@"your app identifier" account:@"user"];

看起来对于iOS 6,苹果建议你使用NSUUID类

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

在ios5.0中已弃用。使用它的identifierForVendor属性 类或ASIdentifierManager的advertisingIdentifier属性 类代替,或者使用NSUUID的UUID方法

. class创建一个UUID并将其写入用户默认数据库

从ios6开始,我们有了符合RFC4122NSUUID

Apple Link: apple_ref for NSUUID

你可以通过下面的代码实现:UIDevice-with-UniqueIdentifier-for-iOS-5

也许你可以用:

[UIDevice currentDevice].identifierForVendor.UUIDString

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

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

< p >可以帮助: 使用下面的代码,它将始终是唯一的,除非你擦除(格式)你的设备

objective - c:

选项1:这将在每次安装时更改

UIDevice *uuid = [NSUUID UUID].UUIDString;

选项2:这将是唯一的每个供应商/开发者苹果帐户

UIDevice *myDevice = [UIDevice currentDevice];
NSString *uuid = [[myDevice identifierForVendor] UUIDString];

斯威夫特5。X:

选项1:这将在每次安装时更改

let uuid = UUID().uuidString

选项2:这将是唯一的每个供应商/开发者苹果帐户

let myDevice = UIDevice.current
let uuid = myDevice.identifierForVendor?.uuidString

ios6中引入的UIDevice identifierForVendor将为您的目的工作。

identifierForVendor是一个字母数字字符串,用于唯一地标识应用程序的供应商的设备。(只读)

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

对于运行在同一设备上的来自同一供应商的应用程序,此属性的值是相同的。对于同一设备上来自不同供应商的应用程序返回不同的值,对于不同设备上的应用程序返回不同的值,与供应商无关。

在ios6.0及更高版本中可用,并在UIDevice.h中声明

对于iOS 5,请参考此链接UIDevice-with-UniqueIdentifier-for-iOS-5

如果有人在寻找替代方案时偶然发现了这个问题。我在IDManager类中遵循了这种方法, 这是不同解的集合。KeyChainUtil是一个从keychain读取的包装器。 你也可以使用hashed MAC address作为一种唯一的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;
}

给你一个小技巧:

/**
@method uniqueDeviceIdentifier
@abstract A unique device identifier is a hash value composed from various hardware identifiers such
as the device’s serial number. It is guaranteed to be unique for every device but cannot
be tied to a user account. [UIDevice Class Reference]
@return An 1-way hashed identifier unique to this device.
*/
+ (NSString *)uniqueDeviceIdentifier {
NSString *systemId = nil;
// We collect it as long as it is available along with a randomly generated ID.
// This way, when this becomes unavailable we can map existing users so the
// new vs returning counts do not break.
if (([[[UIDevice currentDevice] systemVersion] floatValue] < 6.0f)) {
SEL udidSelector = NSSelectorFromString(@"uniqueIdentifier");
if ([[UIDevice currentDevice] respondsToSelector:udidSelector]) {
systemId = [[UIDevice currentDevice] performSelector:udidSelector];
}
}
else {
systemId = [NSUUID UUID];
}
return systemId;
}

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

下面的代码有助于获得UDID:

        udid = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
NSLog(@"UDID : %@", udid);

使用上面提到的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;

这是我用来获取iOS 5和iOS 6,7的ID的代码:

- (NSString *) advertisingIdentifier
{
if (!NSClassFromString(@"ASIdentifierManager")) {
SEL selector = NSSelectorFromString(@"uniqueIdentifier");
if ([[UIDevice currentDevice] respondsToSelector:selector]) {
return [[UIDevice currentDevice] performSelector:selector];
}
}
return [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
}
+ (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;
}

我们可以在ios7中使用identifierForVendor

-(NSString*)uniqueIDForDevice
{
NSString* uniqueIdentifier = nil;
if( [UIDevice instancesRespondToSelector:@selector(identifierForVendor)] ) { // >=iOS 7
uniqueIdentifier = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
} else { //<=iOS6, Use UDID of Device
CFUUIDRef uuid = CFUUIDCreate(NULL);
//uniqueIdentifier = ( NSString*)CFUUIDCreateString(NULL, uuid);- for non- ARC
uniqueIdentifier = ( NSString*)CFBridgingRelease(CFUUIDCreateString(NULL, uuid));// for ARC
CFRelease(uuid);
}
}
return uniqueIdentifier;
}

——重要提示——

UDID和identifierForVendor是不同的:——

1.) On uninstalling  and reinstalling the app identifierForVendor will change.


2.) The value of identifierForVendor remains the same for all the apps installed from the same vendor on the device.


3.) The value of identifierForVendor also changes for all the apps if any of the app (from same vendor) is reinstalled.

从iOS 7开始,苹果在所有公共api中都隐藏了UDID。任何以FFFF开头的UDID都是假ID。以前工作的“发送UDID”应用程序不能再用于为测试设备收集UDID。(叹息)

当设备连接到XCode(在管理器中)时,UDID会显示出来,当设备连接到iTunes时(尽管你必须单击“Serial Number”才能显示标识符)。

如果你需要获取设备的UDID来添加到配置配置文件中,并且不能自己在XCode中完成,你将不得不从iTunes中复制/粘贴它。

自(iOS 7's发布)以来,有没有一种方法可以在PC/Mac上不使用iTunes获得UDID ?< / >

你可以使用

NSString *sID = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];

这是唯一的设备在所有应用程序。

我也遇到了一些问题,解决方法很简单:

    // Get Bundle Info for Remote Registration (handy if you have more than one app)
NSString *appName = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleDisplayName"];
NSString *appVersion = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"];




// Get the users Device Model, Display Name, Unique ID, Token & Version Number
UIDevice *dev = [UIDevice currentDevice];
NSString *deviceUuid=[dev.identifierForVendor  UUIDString];


NSString *deviceName = dev.name;

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

获得UDID的有效方法:

  1. 在应用程序中启动一个web服务器,有两个页面:一个应该返回专门制作的MobileConfiguration配置文件,另一个应该收集UDID。更多信息在这里在这里在这里
  2. 你从应用程序中打开移动Safari的第一页,它会将你重定向到设置。应用程序要求安装配置文件。在你安装概要文件后,UDID被发送到第二个网页,你可以从应用程序内部访问它。App拥有所有必要的权利和不同的沙盒规则)。

使用RoutingHTTPServer的例子:

import UIKit
import RoutingHTTPServer


@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var bgTask = UIBackgroundTaskInvalid
let server = HTTPServer()


func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
application.openURL(NSURL(string: "http://localhost:55555")!)
return true
}


func applicationDidEnterBackground(application: UIApplication) {
bgTask = application.beginBackgroundTaskWithExpirationHandler() {
dispatch_async(dispatch_get_main_queue()) {[unowned self] in
application.endBackgroundTask(self.bgTask)
self.bgTask = UIBackgroundTaskInvalid
}
}
}
}


class HTTPServer: RoutingHTTPServer {
override init() {
super.init()
setPort(55555)
handleMethod("GET", withPath: "/") {
$1.setHeader("Content-Type", value: "application/x-apple-aspen-config")
$1.respondWithData(NSData(contentsOfFile: NSBundle.mainBundle().pathForResource("udid", ofType: "mobileconfig")!)!)
}
handleMethod("POST", withPath: "/") {
let raw = NSString(data:$0.body(), encoding:NSISOLatin1StringEncoding) as! String
let plistString = raw.substringWithRange(Range(start: raw.rangeOfString("<?xml")!.startIndex,end: raw.rangeOfString("</plist>")!.endIndex))
let plist = NSPropertyListSerialization.propertyListWithData(plistString.dataUsingEncoding(NSISOLatin1StringEncoding)!, options: .allZeros, format: nil, error: nil) as! [String:String]


let udid = plist["UDID"]!
println(udid) // Here is your UDID!


$1.statusCode = 200
$1.respondWithString("see https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/iPhoneOTAConfiguration/ConfigurationProfileExamples/ConfigurationProfileExamples.html")
}
start(nil)
}
}

下面是udid.mobileconfig的内容:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PayloadContent</key>
<dict>
<key>URL</key>
<string>http://localhost:55555</string>
<key>DeviceAttributes</key>
<array>
<string>IMEI</string>
<string>UDID</string>
<string>PRODUCT</string>
<string>VERSION</string>
<string>SERIAL</string>
</array>
</dict>
<key>PayloadOrganization</key>
<string>udid</string>
<key>PayloadDisplayName</key>
<string>Get Your UDID</string>
<key>PayloadVersion</key>
<integer>1</integer>
<key>PayloadUUID</key>
<string>9CF421B3-9853-9999-BC8A-982CBD3C907C</string>
<key>PayloadIdentifier</key>
<string>udid</string>
<key>PayloadDescription</key>
<string>Install this temporary profile to find and display your current device's UDID. It is automatically removed from device right after you get your UDID.</string>
<key>PayloadType</key>
<string>Profile Service</string>
</dict>
</plist>

配置文件安装将失败(我没有费心实现预期的响应,参见文档),但应用程序将获得正确的UDID。你还应该签名mobileconfig

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

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

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

iOS 11引入了DeviceCheck框架。它有一个完整的解决方案,唯一地识别设备。

苹果在iOS 11中添加了一个名为DeviceCheck的新框架,它将帮助你非常容易地获得唯一标识符。 阅读此表格了解更多信息。 https://medium.com/@santoshbotre01/unique-identifier-for-the-ios-devices-590bb778290d < / p >