UIDevice uniqueIdentifier已弃用 – 现在该做什么?

iOS5及更高版本中,UIDevice的uniqueIdentifier属性已被弃用 。 似乎没有其他方法或财产可用或即将出现。

我们现有的许多应用程序都严格依赖于此属性来唯一标识特定的设备。 任何人都可以提出任何想法,我们可以如何处理这个问题呢?

从文档的build议是…

特别注意事项

不要使用uniqueIdentifier属性。 要创build特定于您的应用程序的唯一标识符,您可以调用CFUUIDCreate函数来创buildUUID ,并使用NSUserDefaults类将其写入默认数据库。

但是,如果用户卸载并重新安装应用程序,则此值不一样。

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

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

编辑:当然,需要总是查询同一接口的MAC。 我想最好的select是en0 。 MAC始终存在,即使接口没有IP /closures。

编辑2:正如其他人指出的,自iOS 6以来的首选解决scheme是- [UIDevice identifierForVendor] 。 在大多数情况下,您应该可以使用它作为旧的替代-[UIDevice uniqueIdentifier] (但是应用程序第一次启动时创build的UUID是Apple似乎希望您使用的)。

编辑3:所以这个重点不会迷失在评论噪声:不要使用MAC作为UUID, 使用MAC创build一个哈希 即使在重新安装和应用程序(如果哈希以相同的方式完成),那么哈希总是会每次创build相同的结果。 无论如何,现在(2013年),除了在iOS <6.0上需要“稳定”的设备标识符,这是不必要的。

编辑4:在iOS 7中,苹果现在在查询MAC时总是返回一个固定值来阻止MAC作为IDscheme的基础。 所以你现在真的应该使用- [UIDevice identifierForVendor]或创build一个安装的UUID。

您可以使用您的替代苹果UDID已经。 kind guy gekitz在UIDevice上写了一个类,它将根据设备的mac地址和bundle标识符生成一些UDID

你可以在github上find代码

基于@moonlight提出的链接,我做了几个testing,似乎是最好的解决scheme。 正如@DarkDust所说的方法去检查总是可用的en0
有两个选项:
uniqueDeviceIdentifier (MAC + CFBundleIdentifier的MD5)
uniqueGlobalDeviceIdentifier (MAC的MD5),这些总是返回相同的值。
在我做的testing下面(用真实的设备):

 #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 – 删除并安装应用程序后,删除并重新安装应用程序XXXX7dc3c577446a2bcbd77935bdXXXX(Wi-Fi)后的(Wi-Fi)

希望它是有用的。

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

看一下这个,

我们可以使用Keychain而不是NSUserDefaults类来存储由CFUUIDCreate创build的UUID

通过这种方式,我们可以避免重新安装UUID重新创build,并获得相同的应用程序相同的UUID甚至用户卸载并重新安装。

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

我用SFHFKeychainUtils试过这种方法,它的作用就像一个魅力。

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

就您所关心的而言,它将成为唯一的用户标识符 。 (甚至比设备标识符更好)。

例:

我正在定义一个用于创buildUUID的自定义方法:

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

然后,您可以将其存储在您的应用首次启动时在KEYCHAIN 。 所以在第一次启动之后,我们可以简单地使用它从keychain,不需要重新生成它。 使用Keychain存储的主要原因是:当您将UUID设置为Keychain时,即使用户完全卸载App并重新安装,它仍然会持续存在。 。 所以,这是存储它的永久方式,这意味着关键将始终是唯一的。

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

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

也许你可以使用:

 [UIDevice currentDevice].identifierForVendor.UUIDString 

苹果的文档描述如下identifierForVender:

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

您可能需要考虑使用OpenUDID ,这是不推荐使用的UDID替代品。

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

  1. 独特的或足够独特的(低概率的碰撞可能是非常可接受的)
  2. 持续重启,恢复,卸载
  3. 不同供应商的应用程序可用(通过CPInetworking获取用户很有用)

OpenUDID满足上述要求,甚至还有一个内置的退出机制供以后考虑。

检查http://OpenUDID.org它指向相应的GitHub。; 希望这可以帮助!

作为一个方面说明,我会回避任何MAC地址的select。 虽然MAC地址看起来像一个诱人而普遍的解决scheme,但请确保这个低悬的水果中毒。 MAC地址是非常敏感的,苹果很可能不赞成访问这个之前,你甚至可以说,“提交这个应用程序”… MACnetworking地址是用来validation某些设备私人兰斯(WLAN)或其他虚拟私人networking(VPN)。 ..它比以前的UDID更敏感!

我相信苹果已经让这个变化让很多人感到厌烦。 我开发了一个适用于iOS的簿记应用程序 ,并提供在线服务来同步在不同设备上所做的更改。 该服务维护所有设备的数据库以及需要传播给他们的更改。 因此知道哪些设备是哪个是重要的。 我正在跟踪使用UIDevice uniqueIdentifier的设备,以及它的价值,这里是我的想法。

  • 生成一个UUID并存储在用户默认? 没有用,因为用户删除应用程序时,这不会持续。 如果稍后再安装,则在线服务不应该创build新的设备logging,这将浪费服务器上的资源,并给出包含相同的设备的列表两次或更多次。 如果用户重新安装了应用程序,用户会看到不止一个“Bob的iPhone”。

  • 生成一个UUID并存储在钥匙串? 这是我的计划,因为即使应用程序被卸载,它仍然存在。 但是,当将iTunes备份恢复到新的iOS设备时,如果备份已encryption,则会传输钥匙串。 如果旧设备和新设备都处于服务状态,这可能导致两个设备包含相同的设备ID。 即使设备名称相同,它们也应在联机服务中列为两个设备。

  • 生成一个哈希的MAC地址和捆绑ID? 这看起来像我所需要的最好的解决scheme。 通过使用捆绑ID进行散列,生成的设备ID不会跨应用程序跟踪设备,并且获取app +设备组合的唯一ID。

有趣的是,苹果公司自己的文档通过计算系统MAC地址的散列值以及包ID和版本来validationMac App Store收据。 所以这似乎是允许的政策,是否通过应用程序审查,我不知道。

它看起来像iOS 6,苹果build议您使用NSUUID类 。

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

在iOS 5.0中弃用。 相反,使用此类的identifierForVendor属性或ASIdentifierManager类的advertisingIdentifier属性,或者使用NSUUID类的UUID方法创buildUUID并将其写入用户默认数据库。

可能会有所帮助:使用下面的代码,除非您擦除(格式化)设备,否则将始终为唯一。

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

我也build议从uniqueIdentifier到这个开放源代码库 (真正的2个简单类别),它们利用设备的MAC地址以及应用程序包标识符在您的应用程序中生成一个唯一的ID,作为UDID的替代品。

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

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

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

你可以在Github上find它:

带有UniqueIdentifier iOS版本的UIDevice


这里是类别(只是.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 

你可以从这个代码实现: UIDevice-with-UniqueIdentifier-for-iOS-5

MAC地址可能被欺骗,这使得这种方法无法将内容绑定到特定的用户或执行黑名单等安全function。

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

也许这是一个好主意,通过电子邮件向这个主题发送电子邮件和/或提出一个错误/function请求,因为他们甚至可能不知道开发人员的全部后果。

在iOS 6中引入的UIDevice identifierForVendor适用于您的目的。

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

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

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

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

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

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

从iOS 6开始,我们有NSUUID类,它符合RFC4122

Apple链接: apple_ref NSUUID

以下代码有助于获取UDID:

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

iOS 11引入了DeviceCheck框架。 它具有唯一识别设备的全面解决scheme。

您可以使用

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

这在所有应用中都是独一无二的。

苹果已经在iOS 11中添加了一个名为DeviceCheck的新框架,这将帮助您非常轻松地获得唯一标识符。 阅读这个表单更多的信息。 https://medium.com/@santoshbotre01/unique-identifier-for-the-ios-devices-590bb778290d

不要使用这些库 – libOmnitureAppMeasurement,它使用uniqueIdentifier哪个苹果不支持了

如果有人偶然发现这个问题,当寻找替代品。 我在IDManager类中遵循了这种方法,这是从不同的解决scheme中收集的。 KeyChainUtil是从钥匙串中读取的包装器。 您也可以使用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; } 
 + (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; } 

We can use identifierForVendor for ios7,

 -(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; } 

–Important Note —

UDID and identifierForVendor are different:—

 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. 

Apple has hidden the UDID from all public APIs, starting with iOS 7. Any UDID that begins with FFFF is a fake ID. The "Send UDID" apps that previously worked can no longer be used to gather UDID for test devices. (sigh!)

The UDID is shown when a device is connected to XCode (in the organizer), and when the device is connected to iTunes (although you have to click on 'Serial Number' to get the Identifier to display.

If you need to get the UDID for a device to add to a provisioning profile, and can't do it yourself in XCode, you will have to walk them through the steps to copy/paste it from iTunes.

Is there a way since (iOS 7's release) to get the UDID without using iTunes on a PC/Mac?

I had got some issue too, and solution is simple:

  // 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; 

A not perfect but one of the best and closest alternative to UDID (in Swift using iOS 8.1 and Xcode 6.1):

Generating a random UUID

 let strUUID: String = NSUUID().UUIDString 

And use KeychainWrapper library:

Add a string value to keychain:

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

Retrieve a string value from keychain:

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

Remove a string value from keychain:

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

This solution uses the keychain, thus the record stored in the keychain will be persisted, even after the app is uninstalled and reinstalled. The only way of deleting this record is to Reset all contents and settings of the device. That is why I mentioned that this solution of substitution is not perfect but stays one of the best solution of replacement for UDID on iOS 8.1 using Swift.

A working way to get UDID:

  1. Launch a web server inside the app with two pages: one should return specially crafted MobileConfiguration profile and another should collect UDID. More info here , here and here .
  2. You open the first page in Mobile Safari from inside the app and it redirects you to Settings.app asking to install configuration profile. After you install the profile, UDID is sent to the second web page and you can access it from inside the app. (Settings.app has all necessary entitlements and different sandbox rules).

An example using 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) } } 

Here are the contents of 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> 

The profile installation will fail (I didn't bother to implement an expected response, see documentation ), but the app will get a correct UDID. And you should also sign the mobileconfig .