193

How can I get a device's unique ID in Swift?

I need an ID to use in the database and as the API-key for my web service in my social app. Something to keep track of this devices daily use and limit its queries to the database.

pkamb
  • 26,648
  • 20
  • 124
  • 157
User
  • 20,562
  • 35
  • 99
  • 185

8 Answers8

413

You can use this (Swift 3):

UIDevice.current.identifierForVendor!.uuidString

For older versions:

UIDevice.currentDevice().identifierForVendor

or if you want a string:

UIDevice.currentDevice().identifierForVendor!.UUIDString


There is no longer a way to uniquely identify a device after the user uninstalled the app(s). The documentation says:

The value in this property remains the same while the app (or another app from the same vendor) is installed on the iOS device. The value changes when the user deletes all of that vendor’s apps from the device and subsequently reinstalls one or more of them.


You may also want to read this article by Mattt Thompson for more details:
http://nshipster.com/uuid-udid-unique-identifier/

Update for Swift 4.1, you will need to use:

UIDevice.current.identifierForVendor?.uuidString
Atomix
  • 12,019
  • 9
  • 36
  • 43
  • perhaps add .UUIDString so that it can actually be sent to a server? – Daniel Galasko Sep 19 '14 at 08:27
  • 2
    Yup. I figured that is the obvious thing to do, but I included it in the answer. – Atomix Sep 19 '14 at 08:45
  • 24
    After app uninstall this number isn't the same anymore. Is there a way to track a device even after app uninstall ? – jmcastel Dec 10 '14 at 18:21
  • 8
    better question is, if its removed after uninstall, how do you delete their account on your server when the ID is no longer in use? – Jason G Sep 28 '15 at 14:55
  • Just note that in Swift 2.0 UIDevice.currentDevice().identifierForVendor is an optional so you might want to unwrap it like so: UIDevice.currentDevice().identifierForVendor!.UUIDString – Benjamin Oct 20 '15 at 07:39
  • @jmcastel you'd save it in the keychain and every time your app launches just check for that before requesting a new one. – Islam Q. Jan 11 '16 at 19:15
  • UIDevice.currentDevice().identifierForVendor!.UUIDString is not returning the same string each time I run aplication on simulator. – Umair Afzal Jun 05 '16 at 03:33
  • 2
    @UmairAfzal Lots of things don't work in the simulator. Did you try it on the real device? – Atomix Jun 05 '16 at 22:53
  • The string is too long. Is it possible to have shorter version? I mean less than 40 Hexadecimals. – Faizan Mubasher Jan 23 '18 at 07:04
  • ```open var identifierForVendor: UUID? { get } // a UUID that may be used to uniquely identify the device, same across apps from a single vendor.``` How can this be the same across apps from a single vendor, when it changes after app reinstall? – KlimczakM May 07 '19 at 05:37
  • @KlimczakM identifierForVendor, After app uninstall, is this number same anymore? – Gagan_iOS Feb 04 '20 at 13:32
  • @jmcastel Yes, if we uninstall all apps, that vendorID will change. for that I have provided a solution below, but somebody down voted it , I don't know why, but I am effectively using that for years. – Shihab May 18 '20 at 21:38
  • let UUIDValue = UIDevice.current.identifierForVendor?.uuidString print("UUID: \(UUIDValue ?? "")") This code gives Id which is same even after reinstalling the app in real device . But the id gets changed in simulator . – Kiran Jul 06 '20 at 12:12
15

You can use devicecheck (in Swift 4) Apple documentation

func sendEphemeralToken() {
        //check if DCDevice is available (iOS 11)

        //get the **ephemeral** token
        DCDevice.current.generateToken {
        (data, error) in
        guard let data = data else {
            return
        }

        //send **ephemeral** token to server to 
        let token = data.base64EncodedString()
        //Alamofire.request("https://myServer/deviceToken" ...
    }
}

Typical usage:

Typically, you use the DeviceCheck APIs to ensure that a new user has not already redeemed an offer under a different user name on the same device.

Server action needs:

See WWDC 2017 — Session 702 (24:06)

more from Santosh Botre article - Unique Identifier for the iOS Devices

Your associated server combines this token with an authentication key that you receive from Apple and uses the result to request access to the per-device bits.

iluvatar_GR
  • 866
  • 12
  • 19
  • 1
    If I'm understand it correctly, token generation is performed using DCDevice.generateToken(), and every call generates a unique, random device_token. Hence, device_token isn't persistent, but ephemeral. What I don't understand is how the server is able to associate an ephemeral token with a device. – user1118764 Jul 03 '17 at 03:11
  • @user1118764 "Set two bits — Application server will responsible for sharing this token and set the bit value." read more here https://medium.com/@santoshbotre01/unique-identifier-for-the-ios-devices-590bb778290d and also here from official documentation https://developer.apple.com/documentation/devicecheck/accessing_and_modifying_the_per_device_data and 702 session https://developer.apple.com/videos/play/wwdc2017/702/ – iluvatar_GR Jul 03 '17 at 15:10
  • 1
    FYI 24:06 is where the slide on DeviceCheck is discussed from WWDC 2017 Session 702 ^ – Garret Kaye Jan 01 '21 at 16:38
11

For Swift 3.X Latest Working Code, Easily usage;

   let deviceID = UIDevice.current.identifierForVendor!.uuidString
   print(deviceID)
SwiftDeveloper
  • 6,588
  • 11
  • 50
  • 75
10

You can use identifierForVendor public property present in UIDevice class

let UUIDValue = UIDevice.currentDevice().identifierForVendor!.UUIDString
        print("UUID: \(UUIDValue)")

EDIT Swift 3:

UIDevice.current.identifierForVendor!.uuidString

END EDIT

Screenshot for property hierarchy

Jonas Franz
  • 488
  • 1
  • 8
  • 16
Jayprakash Dubey
  • 32,447
  • 16
  • 161
  • 169
2

Swift 2.2

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

    let userDefaults = NSUserDefaults.standardUserDefaults()

    if userDefaults.objectForKey("ApplicationIdentifier") == nil {
        let UUID = NSUUID().UUIDString
        userDefaults.setObject(UUID, forKey: "ApplicationIdentifier")
        userDefaults.synchronize()
    }
    return true
}

//Retrieve
print(NSUserDefaults.standardUserDefaults().valueForKey("ApplicationIdentifier")!)
n.by.n
  • 2,308
  • 18
  • 31
  • 4
    It is useless if the user deletes application because userdefaults also get deleted with application uninstallation. – Rehan Ali Aug 30 '19 at 07:01
0
if (UIDevice.current.identifierForVendor?.uuidString) != nil
        {
            self.lblDeviceIdValue.text = UIDevice.current.identifierForVendor?.uuidString
        }
Davender Verma
  • 399
  • 1
  • 10
  • 2
    Please comment your code and/or offer details and an explanation of how this solves the posted question. – RyanNerd Feb 05 '20 at 06:41
-2
class func uuid(completionHandler: @escaping (String) -> ()) {
    if let uuid = UIDevice.current.identifierForVendor?.uuidString {
        completionHandler(uuid)
    }
    else {
        // If the value is nil, wait and get the value again later. This happens, for example, after the device has been restarted but before the user has unlocked the device.
        // https://developer.apple.com/documentation/uikit/uidevice/1620059-identifierforvendor?language=objc
        DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
            uuid(completionHandler: completionHandler)
        }
    }
}
Joey
  • 2,774
  • 2
  • 25
  • 32
-20

I've tried with

let UUID = UIDevice.currentDevice().identifierForVendor?.UUIDString

instead

let UUID = NSUUID().UUIDString

and it works.

Matt
  • 1
  • 3