UIDevice uniqueIdentifier已弃用 - 现在该怎么办?

时间:2011-08-09 08:27:23

标签: ios deprecated uidevice

iOS 5 中显示the UIDevice uniqueIdentifier property is deprecated并且在iOS 7及更高版本中无法显示。似乎没有替代方法或财产可用或即将出现。

我们的许多现有应用都严格依赖此属性来唯一标识特定设备。我们如何处理这个问题呢?

the documentation in 2011-2012的建议是:

  

特别注意事项

     

不要使用uniqueIdentifier属性。创建特定的唯一标识符   在您的应用中,您可以调用CFUUIDCreate函数创建UUID,然后编写   它使用NSUserDefaults类到默认数据库。

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

32 个答案:

答案 0 :(得分:270)

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

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

编辑:当然,需要始终查询同一界面的MAC。我猜最好的选择是使用en0。即使接口没有IP /已关闭,MAC也始终存在。

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

编辑3:所以这个主要观点不会在评论噪音中丢失:不要将 MAC 用作UUID,创建一个使用MAC的哈希。每次都会创建相同的结果,即使在重新安装和应用程序中也是如此(如果散列以相同的方式完成)。无论如何,现在(2013),除了你需要iOS上的“稳定”设备标识符外,这不再是必要的。 6.0。

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

答案 1 :(得分:91)

您已经可以使用替代Apple UDID。善良的家伙gekitz在UIDevice上写了类别,它会根据设备的mac-address和bundle identifier生成某种UDID

您可以在github

上找到代码

答案 2 :(得分:61)

基于@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模式)UDID
  XXXX7dc3c577446a2bcbd77935bdXXXX - (AirPlane模式)GlobalAppUDID

     

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

希望它有用。

修改
正如其他人所指出的那样,iOS 7中的此解决方案不再有用,因为uniqueIdentifier不再可用,现在查询MAC地址始终是02:00:00:00:00:00

答案 3 :(得分:56)

检查一下,

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

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

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

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

答案 4 :(得分:47)

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

就您而言,它实际上会成为唯一的用户标识符。 (甚至比设备标识符更好)。

示例:

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

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

然后,您可以在首次启动应用时将其存储在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"];

答案 5 :(得分:17)

也许你可以使用:

[UIDevice currentDevice].identifierForVendor.UUIDString

Apple的文档描述了identifierForVender,如下所示:

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

答案 6 :(得分:14)

您可以考虑使用OpenUDID,它是已弃用的UDID的替代品。

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

  1. 独特或足够独特(低概率碰撞是 可能非常接受)
  2. 重新启动,恢复,卸载时的持久性
  3. 可在不同供应商的应用程序之间使用(对于通过CPI网络获取用户非常有用) -
  4. OpenUDID实现了上述目标,甚至还有一个内置的选择退出机制供以后考虑。

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

    作为旁注,我会回避任何MAC地址替代方案。虽然MAC地址看起来像一个诱人的通用解决方案,但请确保这种低悬的水果中毒。 MAC地址非常敏感,Apple甚至可以拒绝访问此地址,甚至可以说“提交此应用程序”...... MAC网络地址用于验证私有设备(WLAN)或其他虚拟专用设备上的某些设备网络(VPN)。 ..它比以前的UDID更敏感!

答案 7 :(得分:11)

我确信苹果公司已经让很多人对这一变化感到恼火。我为iOS开发了bookkeeping app并拥有在线服务来同步在不同设备上进行的更改。该服务维护所有设备的数据库以及需要传播给它们的更改。因此,了解哪些设备是哪些设备非常重要。我正在使用UIDevice uniqueIdentifier跟踪设备以及它的价值,这是我的想法。

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

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

  • 生成MAC地址和包ID的哈希值? 这看起来是我需要的最佳解决方案。通过使用包ID进行散列,生成的设备ID不会启用跨应用程序跟踪设备,并且我会获得应用+设备组合的唯一ID。

有趣的是,Apple自己的文档是指通过计算系统MAC地址的散列加上捆绑包ID和版本来验证 Mac App Store收据。所以这似乎是政策所允许的,无论是通过我还不知道的应用评论。

答案 8 :(得分:11)

对于iOS 6,Apple建议您使用the NSUUID class

现在uniqueIdentifier属性{{1}}文档中的消息:

  

在iOS 5.0中已弃用。使用this的identifierForVendor属性   class或ASIdentifierManager的advertisingIdentifier属性   相反,适当地使用类,或使用NSUUID的UUID方法   用于创建UUID并将其写入用户默认数据库的类。

答案 9 :(得分:11)

可能会有所帮助: 使用下面的代码,除了擦除(格式化)你的设备外,它总是唯一的。

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

答案 10 :(得分:7)

我还建议从uniqueIdentifier切换到this open source library(真正的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

答案 11 :(得分:5)

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

答案 12 :(得分:4)

MAC地址可能是欺骗性的,这使得这种方法无法将内容绑定到特定用户或实施黑名单等安全功能。

经过一些进一步的研究后,在我看来,我们现在还没有一个合适的选择。我非常希望Apple能够重新考虑他们的决定。

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

答案 13 :(得分:4)

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

}

答案 14 :(得分:4)

iOS 6中引入的

UIDevice identifierForVendor可用于您的目的。

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

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

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

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

中声明

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

答案 15 :(得分:3)

以下代码有助于获取UDID:

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

答案 16 :(得分:3)

这是我用来获取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];
}

答案 17 :(得分:2)

从iOS 6开始,我们的NSUUID课程符合RFC4122

Apple Link:apple_ref for NSUUID

答案 18 :(得分:2)

iOS 11引入了DeviceCheck框架。它具有全面的解决方案,可以唯一识别设备。

答案 19 :(得分:1)

获取UDID的工作方式:

  1. 在应用程序内部启动一个Web服务器,其中包含两个页面:一个应该返回特制的MobileConfiguration配置文件,另一个应该收集UDID。更多信息hereherehere
  2. 您从应用程序内部打开Mobile Safari中的第一页,它会将您重定向到Settings.app,要求安装配置文件。安装配置文件后,UDID将发送到第二个网页,您可以从应用程序内部访问它。 (Settings.app具有所有必要的权利和不同的沙盒规则)。
  3. 使用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>
    

    配置文件安装将失败(我没有打算实现预期的响应,请参阅documentation),但应用程序将获得正确的UDID。你还应该sign the mobileconfig

答案 20 :(得分:1)

Apple在iOS 11中添加了一个名为DeviceCheck的新框架,它可以帮助您轻松获取唯一标识符。 阅读此表格了解更多信息。 https://medium.com/@santoshbotre01/unique-identifier-for-the-ios-devices-590bb778290d

答案 21 :(得分:1)

您可以使用

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

这对于所有应用程序中的设备都是唯一的。

答案 22 :(得分:0)

我们可以将 identifierForVendor 用于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;
}

- 重要提示---

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.

答案 23 :(得分:0)

从iOS 7开始,Apple已将UDID隐藏在所有公共API中。任何以FFFF开头的UDID都是假ID。之前工作的“发送UDID”应用程序不能再用于收集测试设备的UDID。 (感叹!)

当设备连接到XCode(在管理器中),以及设备连接到iTunes时,会显示UDID(尽管您必须单击“序列号”才能显示标识符。

如果您需要获取要添加到配置文件的设备的UDID,并且无法在XCode中自行完成,则必须完成从iTunes复制/粘贴它的步骤。

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

答案 24 :(得分:0)

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

答案 25 :(得分:0)

我也有一些问题,解决方案很简单:

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

答案 26 :(得分:0)

一个不完美但是最好和最接近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的最佳解决方案之一。

答案 27 :(得分:0)

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

struct.pack('i',x)
struct.error: integer out of range for 'i' format code

答案 28 :(得分:0)

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

答案 29 :(得分:0)

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

答案 30 :(得分:-1)

不要使用这些库 - libOmnitureAppMeasurement,它确实使用了apple不再支持的uniqueIdentifier

答案 31 :(得分:-2)

小黑客:

/**
 @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;
}