我们许多现有的应用程序都高度依赖此属性来唯一标识特定设备。那么我们该如何解决这个问题呢?
特别注意事项
不要使用uniqueIdentifier属性。要创建与您的应用程序特定的唯一标识符,您可以调用CFUUIDCreate函数创建UUID,并使用NSUserDefaults类将其写入默认数据库。
但是如果用户卸载并重新安装该应用程序,该值将不同。
我们许多现有的应用程序都高度依赖此属性来唯一标识特定设备。那么我们该如何解决这个问题呢?
特别注意事项
不要使用uniqueIdentifier属性。要创建与您的应用程序特定的唯一标识符,您可以调用CFUUIDCreate函数创建UUID,并使用NSUserDefaults类将其写入默认数据库。
但是如果用户卸载并重新安装该应用程序,该值将不同。
let deviceIdentifier: String = (UIDevice.current.identifierForVendor?.uuidString)!
NSLog("output is : %@", deviceIdentifier)
标签
。NSString *sID = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
苹果在iOS 11中新增了一个名为DeviceCheck的框架,可以帮助您轻松获取唯一标识符。阅读此表单以获取更多信息。https://medium.com/@santoshbotre01/unique-identifier-for-the-ios-devices-590bb778290d
一个不完美但是最好和最接近UDID的替代方案(在使用iOS 8.1和Xcode 6.1的Swift中):
生成一个随机UUID
let strUUID: String = NSUUID().UUIDString
并使用KeychainWrapper库:
将字符串值添加到钥匙串中:
let saveSuccessful: Bool = KeychainWrapper.setString("Some String", forKey: "myKey")
从钥匙串中检索字符串值:
let retrievedString: String? = KeychainWrapper.stringForKey("myKey")
从钥匙串中删除字符串值:
let removeSuccessful: Bool = KeychainWrapper.removeObjectForKey("myKey")
该解决方案使用钥匙串,因此存储在钥匙串中的记录将被持久化,即使应用程序被卸载并重新安装后也是如此。删除此记录的唯一方法是重置设备的所有内容和设置。这就是为什么我提到,虽然这种替代方案并不完美,但在使用Swift的iOS 8.1上,仍然是最好的UDID替代方案之一。
IDManager
类中采用了这种方法。这是从不同解决方案中收集的。KeyChainUtil是一个包装器,用于从钥匙串中读取。您还可以使用散列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;
}
我们可以在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.
+ (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;
}
我也遇到了一些问题,解决方案很简单:
// 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;
NSLog(@"%@",[[UIDevice currentDevice]identifierForVendor]);
NSLog(@“%@”,[[UIDevice currentDevice] identifierForVendor]);
自iOS 7开始,苹果已经从所有公共API中隐藏了UDID。任何以FFFF开头的UDID都是伪造的ID。之前可以使用的“发送UDID”应用程序现在不能再用于收集测试设备的UDID。(叹气!)
当设备连接到XCode(在组织者中)时,会显示UDID;当设备连接到iTunes时也会显示UDID(尽管您必须单击“序列号”才能显示标识符)。
如果您需要获取设备的UDID以添加到配置文件中,而无法在XCode中自行完成,则必须引导他们按照步骤从iTunes中复制/粘贴它。