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

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

2011-2012年的文件建议:

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

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


当前回答

给你一个小技巧:

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

其他回答

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

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

你可以使用

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

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

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

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

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

编辑2:正如其他人指出的那样,自iOS 6以来首选的解决方案是-[UIDevice identifierForVendor]。在大多数情况下,你应该可以使用它来替换旧的-[UIDevice uniqueIdentifier](但是当应用程序第一次启动时创建的UUID似乎是苹果想要你使用的)。

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

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

获得UDID的有效方法:

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. 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).

一个使用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上签名。

你可以通过以下代码实现:uidevice -with- uniqueidentifier -for ios -5