By Oliver Pearmain


2011-08-09 08:27:23 8 Comments

It has just come to light that the UIDevice uniqueIdentifier property is deprecated in iOS 5 and unavailable in iOS 7 and above. No alternative method or property appears to be available or forthcoming.

Many of our existing apps are tightly dependent on this property for uniquely identifying a particular device. How might we handle this problem going forward?

The suggestion from the documentation in 2011-2012 was:

Special Considerations

Do not use the uniqueIdentifier property. To create a unique identifier specific to your app, you can call the CFUUIDCreate function to create a UUID, and write it to the defaults database using the NSUserDefaults class.

However this value won't be the same if a user uninstalls and re-installs the app.

30 comments

@Santosh Botre 2017-08-24 05:28:41

Apple has added a new framework in iOS 11 called DeviceCheck which will help you to get the unique identifier very easily. Read this form more information. https://medium.com/@santoshbotre01/unique-identifier-for-the-ios-devices-590bb778290d

@Santosh Botre 2017-06-21 04:56:49

iOS 11 has introduced the DeviceCheck framework. It has a fullproof solution for uniquely identifying the device.

@Dhaval 2014-02-25 05:34:33

You can use

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

Which is unique for the device in all application.

@Ganesh 2016-09-17 05:22:15

For Swift 3.0 please use below code.

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

@Santosh Botre 2017-06-21 04:55:13

iOS 11 has introduced the DeviceCheck framework. It has a fullproof solution for uniquely identifying the device.

@Ankit garg 2016-12-30 16:24:12

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

@Samir Jwarchan 2012-09-20 11:03:31

Create your own UUID and then store it in the Keychain. Thus it persists even when your app gets uninstalled. In many cases it also persists even if the user migrates between devices (e.g. full backup and restore to another device).

Effectively it becomes a unique user identifier as far as you're concerned. (even better than device identifier).

Example:

I am defining a custom method for creating a UUID as :

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

You can then store it in KEYCHAIN on the very first launch of your app. So that after first launch, we can simply use it from keychain, no need to regenerate it. The main reason for using Keychain to store is: When you set the UUID to the Keychain, it will persist even if the user completely uninstalls the App and then installs it again. . So, this is the permanent way of storing it, which means the key will be unique all the way.

     #import "SSKeychain.h"
     #import <Security/Security.h>

On applictaion launch include the following code :

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

Download SSKeychain.m and .h file from sskeychain and Drag SSKeychain.m and .h file to your project and add "Security.framework" to your project. To use UUID afterwards simply use :

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

@CReaTuS 2013-07-10 01:52:51

Will this work in iOS 7 at correctly ?

@CReaTuS 2013-07-10 05:34:10

Because a identifierForVendor is working is not perfectly. In some case can return a nil or 0x0. This method it seems is working at perfectly

@mindbomb 2013-10-14 16:20:16

anyone validated this is working on iOS7 after uninstall/reinstall cycle + verified apple app submission?

@deko 2017-04-28 09:01:58

I've started using this solution. Several tests on 2 devices (rebuild, reinstall, device shut down) showed me that id is the same. iOS 10.3.

@bzz 2015-06-04 17:55:30

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.

@King-Wizard 2014-12-01 01:52:14

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.

@Ahmet Kazim Günay 2014-04-18 19:39:26

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;

@Preet 2014-01-23 08:26:16

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?

@Mat 2011-10-24 09:32:16

Based on the link proposed by @moonlight, i did several tests and it seems to be the best solution. As @DarkDust says the method goes to check en0 which is always available.
There are 2 options:
uniqueDeviceIdentifier (MD5 of MAC+CFBundleIdentifier)
and uniqueGlobalDeviceIdentifier(MD5 of the MAC), these always returns the same values.
Below the tests i've done (with the real device):

#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 mode)UDID
XXXX7dc3c577446a2bcbd77935bdXXXX - (AirPlane mode)GlobalAppUDID

XXXX21f1f19edff198e2a2356bf4XXXX - (Wi-Fi)after removing and reinstalling the app XXXX7dc3c577446a2bcbd77935bdXXXX (Wi-Fi) after removing and installing the app

Hope it's useful.

EDIT:
As others pointed out, this solution in iOS 7 is no longer useful since uniqueIdentifier is no longer available and querying for MAC address now returns always 02:00:00:00:00:00

@erator 2012-01-16 20:46:50

thanks for the extra effort to test this!

@Sarim Sidd 2013-08-03 09:40:50

this wont work on iOS7, Apple eliminates the use of MAC address.

@Mat 2013-08-05 07:33:05

@SarimSidd For now informations about iOS 7 are under NDA, we can't discuss here.

@HDdeveloper 2013-12-03 09:19:54

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.

@Avis 2014-09-23 18:46:51

are you sure ? can we use identifierForVendor for ios7,?

@mahesh chowdary 2013-11-26 09:25:37

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

@Grzegorz Krukowski 2013-09-17 10:15:04

This is code I'm using to get ID for both iOS 5 and iOS 6, 7:

- (NSString *) advertisingIdentifier
{
    if (!NSClassFromString(@"ASIdentifierManager")) {
        SEL selector = NSSelectorFromString(@"uniqueIdentifier");
        if ([[UIDevice currentDevice] respondsToSelector:selector]) {
            return [[UIDevice currentDevice] performSelector:selector];
        }
    }
    return [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
}

@Basil Bourque 2014-02-22 11:50:49

What do you do about the compiler warning PerformSelector may cause a leak because its selector is unknown?

@codeplasma 2014-04-09 08:11:34

You can no more use advertisingIdentifier for this purpose as Apple will reject it. More info: techcrunch.com/2014/02/03/…

@Komposr 2013-09-04 12:09:16

Using the SSKeychain and code mentioned above. Here's code to copy/paste (add SSKeychain module):

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

}

@santify 2013-08-09 18:40:49

Following code helps to get UDID:

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

@karim 2013-05-13 15:08:18

If someone stumble upon to this question, when searching for an alternative. I have followed this approach in IDManager class, This is a collection from different solutions. KeyChainUtil is a wrapper to read from keychain. You can also use the hashed MAC address as a kind of unique 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;
}

@DarkDust 2011-08-09 08:37:32

A UUID created by CFUUIDCreate is unique if a user uninstalls and re-installs the app: you will get a new one each time.

But you might want it to be not unique, i. e. it should stay the same when the user uninstalls and re-installs the app. This requires a bit of effort, since the most reliable per-device-identifier seems to be the MAC address. You could query the MAC and use that as UUID.

Edit: One needs to always query the MAC of the same interface, of course. I guess the best bet is with en0. The MAC is always present, even if the interface has no IP/is down.

Edit 2: As was pointed out by others, the preferred solution since iOS 6 is -[UIDevice identifierForVendor]. In most cases, you should be able use it as a drop-in replacement to the old -[UIDevice uniqueIdentifier] (but a UUID that is created when the app starts for the first time is what Apple seems to want you to use).

Edit 3: So this major point doesn't get lost in the comment noise: do not use the MAC as UUID, create a hash using the MAC. That hash will always create the same result every time, even across reinstalls and apps (if the hashing is done in the same way). Anyways, nowadays (2013) this isn't necessary any more except if you need a "stable" device identifier on iOS < 6.0.

Edit 4: In iOS 7, Apple now always returns a fixed value when querying the MAC to specifically thwart the MAC as base for an ID scheme. So you now really should use -[UIDevice identifierForVendor] or create a per-install UUID.

@Oliver Pearmain 2011-08-09 08:46:16

Does the mac address not change depending on whether the user is connected via Wifi or not?

@DarkDust 2011-08-09 08:52:05

No, the IP does, but not the MAC. The MAC is unique to the interface.

@user102008 2011-08-27 01:01:29

@DarkDust: but since the active interface changes when you switch from wifi to cellular modem, the MAC address of the active interface should also change; unless you always pick a particular interface to get the MAC

@DarkDust 2011-08-27 08:45:05

@user102008: I assumed it to be obvious to always query, say, en0, since the MAC is present even if the interface is down. But you're right, it probably isn't obvious.

@DougW 2012-03-26 18:18:24

Just check it the first time, then stash it in the Keychain. It will persist even if the user uninstall/reinstalls the application. Someone mentioned this in another answer as well.

@xgalaxy 2012-03-28 20:46:35

Using MAC address is no longer a solution. Apple is going to crack down on it's usage, along with UDID. Apple is telling developers that MAC address is not the solution.

@jake_hetfield 2012-03-30 08:47:54

Unique means it's the only one in existence. Unique does not mean it has to be changing every time. So either way if the UUID changes or not every time the app is re-installed or not, it is still unique if there are no other instances of the app with the same ID in existence.

@spankmaster79 2012-04-03 13:28:13

And now please somebody tell me a way to use an identifier I can ask the customer to tell me, becaus i do not have the device and need to register his device...

@DarkDust 2012-08-24 07:58:57

@Jay Imerman: To get a UDID, you can simply hash the MAC of en0 just like suggested. It will identify the device and stay the same across apps and when you reinstall your app. Querying the UDID like you can see in iTunes is deprecated and might disappear soon (AFAIK Apple has even started rejecting apps using uniqueIdentifier, but I don't know for sure).

@AlfeG 2012-10-23 09:31:11

Has anyone researched on legality aspect of Mac Address usage? If UUID were a problem with privacy for Apple, then MacAddresses can be even bigger problem.

@DarkDust 2013-03-27 17:22:37

@Roger Nolan: Please don't edit other people's answers and add stuff that looks like it came from the original author. Thanks.

@DarkDust 2013-03-27 17:34:00

@AlfeG: With the proposed hashing of a MAC, the MAC itself would never be transmitted. But using a real UUID that you create on the first app start is considered to be the best solution.

@Rog 2013-04-08 14:27:23

@DarkDust why? Isn't Stack OVerflow a community resource? I would guess that if SO wanted that behaviour they would enforce it. Still, you are free to edit on top of the other edits to show the history at the expense of readability if it's important to you.

@DarkDust 2013-04-08 16:30:51

@RogerNolan As long as post is not a community answer, the edits are for correcting mistakes and such things, not for adding new stuff. There's a reason you have earn the privilege. Imagine I edit your answer and write some BS, people would think you would've written that. I doubt you'd like that :-) But you don't get notified that an edit happened, I only found out by accident.

@Rog 2013-04-11 10:19:31

@DarkDust I think that you earn the right so you don't edit in BS (as I didn't) but do add sensible upgrades that contribute to the greater resource. I think you are mistaken: SO is about knowledge and making answers as good as they can be, it is not about the sanctity of original postings. That said, I don't think it's worth carrying on the discussion :-)

@Idan 2013-05-20 18:30:47

Apple now rejects apps that uses hashed MAC.

@Sulthan 2013-06-21 13:50:18

@Idan Not only that, if you check iOS 7 API changes, you won't be able to get MAC address at all.

@CReaTuS 2013-07-10 02:56:11

@DarkDust So, in new iOS 7 and if i using CFUUIDCReate, i will not have any problems? Because, it seems, identifierForVendor is not work at perfectly, in some case will return a nil or 0x0

@DarkDust 2013-07-29 10:23:10

@CReaTuS The CFUUIDCreate way will always work.

@CReaTuS 2013-07-30 04:24:12

@DarkDust There was a is not alternative of old UDID function. When user is reinstall app, then CFUUID is changing to another, so this CFUUID is just simple variable. Thanks for answer

@taber 2013-09-25 21:24:38

Of note: identifierForVendor became available in iOS 6.0 so it doesn't require iOS 7. To get a string from identifierForVendor you can use [[[UIDevice currentDevice] identifierForVendor] UUIDString]

@βhargavḯ 2013-10-11 09:05:41

@DarkDust If I create UUID using CFUUIDCreate or use identifierForVendor, then it is getting changed on app re-install (removing app and installing again). Can you guide me what should I use as part of this to get life-time id on iOS6 onwards ?

@snibbe 2015-10-21 23:48:01

In SWIFT this is the syntax UIDevice.currentDevice().identifierForVendor or if you want a string UIDevice.currentDevice().identifierForVendor!.UUIDString via How to get a unique device ID in Swift

@CyberMew 2017-08-22 05:33:05

I believe the identifierForVendor changes upon app update.

@chown 2011-10-30 18:17:24

I would also suggest changing over from uniqueIdentifier to this open source library (2 simple categories really) that utilize the device’s MAC Address along with the App Bundle Identifier to generate a unique ID in your applications that can be used as a UDID replacement.

Keep in mind that unlike the UDID this number will be different for every app.

You simply need to import the included NSString and UIDevice categories and call [[UIDevice currentDevice] uniqueDeviceIdentifier] like so:

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

You can find it on Github here:

UIDevice with UniqueIdentifier for iOS 5


Here are the categories (just the .m files - check the github project for the headers):

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

@Alex Nolasco 2013-08-07 04:15:49

author claims this will not work with iOS 7 >.<

@Roberto 2013-08-27 04:25:58

Starting in iOS 7, Apple will return a constant value for the MAC address. It makes perfect sense. The MAC address is sensitive.

@bluefloyd8 2013-09-17 02:09:12

not for iOS7 :(

@DShah 2012-10-17 11:57:53

From iOS 6 onwards, we have NSUUID class which complies RFC4122

Apple Link : apple_ref for NSUUID

@Nagarjuna 2013-06-05 14:41:56

Dont use these libraries - libOmnitureAppMeasurement, It does use uniqueIdentifier which apple doesnt support anymore

@Mahendra Liya 2013-04-08 11:56:40

UIDevice identifierForVendor introduced in iOS 6 would work for your purposes.

identifierForVendor is an alphanumeric string that uniquely identifies a device to the app’s vendor. (read-only)

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

The value of this property is the same for apps that come from the same vendor running on the same device. A different value is returned for apps onthe same device that come from different vendors, and for apps on different devices regardles of vendor.

Available in iOS 6.0 and later and declared in UIDevice.h

For iOS 5 refer this link UIDevice-with-UniqueIdentifier-for-iOS-5

@SachinVsSachin 2012-10-31 08:45:01

You can achieve from this code : UIDevice-with-UniqueIdentifier-for-iOS-5

@digipeople 2013-05-17 08:55:04

Little hack for you:

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

@ylechelle 2012-03-28 19:16:06

You may want to consider using OpenUDID which is a drop-in replacement for the deprecated UDID.

Basically, to match the UDID, the following features are required:

  1. unique or sufficiently unique (a low probability collision is probably very acceptable)
  2. persistence across reboots, restores, uninstalls
  3. available across apps of different vendors (useful to acquire users via CPI networks) -

OpenUDID fulfills the above and even has a built-in Opt-Out mechanism for later consideration.

Check http://OpenUDID.org it points to the corresponding GitHub. Hope this helps!

As a side note, I would shy away from any MAC address alternative. While the MAC address appears like a tempting and universal solution, be sure that this low hanging fruit is poisoned. The MAC address is very sensitive, and Apple may very well deprecate access to this one before you can even say "SUBMIT THIS APP"... the MAC network address is used to authenticate certain devices on private lans (WLANs) or other virtual private networks (VPNs). .. it's even more sensitive than the former UDID!

@jake_hetfield 2012-03-30 12:31:39

I'm really curious how this works? The code is written in Objective-C, but there is no other good solution that fits the requirements above, so what makes this framework different? The solution that this framework is using should also be possible to post as a suggested answer here...

@Jay Imerman 2012-08-23 15:13:23

I concur - MAC address can be manually configured as well ("cloned"), although it is not likely for the most part. I must protest the D in UDID. This is not a Device ID, it is a UUID (Universally Unique Identifier). The Device ID is stamped by Apple from the factory on each device in ROM.

@mindbomb 2013-10-14 16:16:39

no good for iOS7

@vishal dharankar 2014-05-03 17:40:25

Best solution for iOS7 as well does whats actually needed to identify a device uniquely

@mkll 2014-12-07 20:18:53

OpenUDID is deprecated and not recommended to use

@ytur 2012-03-06 15:16:50

check this out,

we can use Keychain instead of NSUserDefaults class, to store UUID created by CFUUIDCreate.

with this way we could avoid for UUID recreation with reinstallation, and obtain always same UUID for same application even user uninstall and reinstall again.

UUID will recreated just when device reset by user.

I tried this method with SFHFKeychainUtils and it's works like a charm.

@Jeevan Takhar 2012-04-22 21:34:48

This method is a solid replacement for UDID. It also has the added benefit of recreating the identifier upon device format (eg. if the device changes owner). However, it's important to note that the keychain can be restored to other devices if the user encrypts their backup. This can result in a situation where multiple devices share the same UUID. To avoid this, set the accessibility of your keychain item to kSecAttrAccessibleAlwaysThisDeviceOnly. This will ensure that your UUID does not migrate to any other device. To access your UUID from other apps, utilise the kSecAttrAccessGroup key.

@lostintranslation 2014-08-06 18:52:11

Where exactly (which key) are you supposed to use to store the UUID in keychain?

@Serhii Mamontov 2011-08-22 08:40:01

You can use your alternative for Apple UDID already. Kind guy gekitz wrote category on UIDevice which will generate some kind of UDID based on device mac-address and bundle identifier.

You can find code on github

@Vincent Guerci 2011-08-22 08:45:47

This implementation is unique (MAC address) for a device across reinstallations, like Apple's uniqueId, but also respect privacy, being also unique for an application (also use bundleId)... A must have imho, that Apple should include in its APIs... instead of deprecating w/o any alternatives.

@jbtule 2011-09-29 00:06:19

Although it uses the old style bsd license with the advertising clause, yuck.

@James 2012-03-04 13:20:36

For anyone else now finding this post, the license has been changed since the above comment by jbtule.

@Tom Andersen 2012-05-16 15:42:51

I don't think that this is too secure. (it may not matter to you) There are 10^14 mac addresses possible. Going through all of them is only about an hour on a fast machine to get the Mac address given the hash. whitepixel.zorinaq.com. Adding the bundle ID does not help, as most would know the bundleID to check.

@Serhii Mamontov 2012-05-16 21:52:13

@TomAndersen there are also some formula about how to calculate real device UDID, so if someone would like to find something, he could do so. This code was suggested for developers, to somehow get unique device ID, it doesn't take into account all those who want to trick backends.

@Nicole 2012-07-19 22:25:54

What about when the phone is sold? What about when you buy a new phone and transfer all your data?

@Will 2013-02-13 11:42:12

As discussed in this commit comment, the library as-is poses a serious privacy leak issue and should not be used:

@Eric 2013-02-18 03:29:57

As mentioned by others, this library does pose a serious privacy leaks: github.com/gekitz/UIDevice-with-UniqueIdentifier-for-iOS-5/…

@Hejazi 2013-06-11 23:41:07

Starting from iOS 7, the system always returns the value 02:00:00:00:00:00 when you ask for the MAC address on any device. Check here: developer.apple.com/library/prerelease/ios/releasenotes/Gene‌​ral/…

@Ashvin Ajadiya 2013-03-12 09:27:31

May help: use below code it will always Unique except you erase(Format) your device.

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

@Durgaprasad 2013-05-30 07:17:19

I used this code. But when I deleted app and again installed I got new Id

@Reuben L. 2013-06-16 17:45:39

this is a simple solution if you don't need a robust method. i'm using it in my app now.

@Ashvin Ajadiya 2014-04-25 09:28:29

@Durgaprasad : it will change always becuase its depend on vendor. For example : 1. If you have install a app with bundleidenedifier : com.abcd.com => then it will change. 2. If you have install two app with bundleidenedifier : com.abcd.com => Then it will not chnage (Keep any one app during)

@diadyne 2013-01-15 18:43:44

Perhaps you can use:

[UIDevice currentDevice].identifierForVendor.UUIDString

Apple's documentation describes identifierForVender as follows:

The value of this property is the same for apps that come from the same vendor running on the same device. A different value is returned for apps on the same device that come from different vendors, and for apps on different devices regardless of vendor.

@James Boutcher 2013-01-15 20:32:11

Curious why nobody brought this up until recently... And now I see it's new with iOS 6.

@Sunil Zalavadiya 2013-04-13 07:08:56

If user update ios and/or install new ios then value of identifierForVendor will change or remain same?

@Mitesh Khatri 2013-09-03 05:15:50

After remove all apps from same vendor then this value will be changed.

@Nate 2012-10-01 09:27:11

It looks like for iOS 6, Apple is recommending you use the NSUUID class.

From the message now in the UIDevice docs for uniqueIdentifier property:

Deprecated in iOS 5.0. Use the identifierForVendor property of this class or the advertisingIdentifier property of the ASIdentifierManager class instead, as appropriate, or use the UUID method of the NSUUID class to create a UUID and write it to the user defaults database.

Related Questions

Sponsored Content

5 Answered Questions

[SOLVED] Rails I18n validation deprecation warning

5 Answered Questions

5 Answered Questions

[SOLVED] using a unique identifier of iPhone or iOS device

  • 2011-09-09 15:16:59
  • Mann
  • 14069 View
  • 4 Score
  • 5 Answer
  • Tags:   iphone ios

2 Answered Questions

[SOLVED] Retrieving device WiFi MAC address with iOS 7

1 Answered Questions

Register each unique iOS device?

3 Answered Questions

3 Answered Questions

[SOLVED] Alternative to iPhone device ID (UDID)

5 Answered Questions

1 Answered Questions

Sponsored Content