# FCUUID: six identifiers, and a table showing exactly when each one changes

> FCUUID hands you a ladder of persistence levels from a value that changes every call to one that survives a system reset, and publishes a table showing which events wipe which value. The migration methods are the part most adopters will actually need.

**fabiocaccamo/FCUUID** — :iphone: :id:  iOS UUID / Universally Unique Identifiers library as alternative to UDID and identifierForVendor.

- Repository: https://github.com/fabiocaccamo/FCUUID
- Stars: 1,645 · Forks: 238
- Language: Objective-C
- License: MIT
- Published: 2026-10-16 · Updated: 2026-10-16 · Language: en
- Canonical page: https://hysenlabs.com/projects/fabiocaccamo-fcuuid

## Six functions, six lifetimes

The API is a ladder, and each rung is a different answer to how long the value should live.

```objective-c
//changes each time (no persistent)
+(NSString *)uuid;

//changes each time (no persistent), but allows to keep in memory more temporary uuids
+(NSString *)uuidForKey:(id<NSCopying>)key;

//changes each time the app gets launched (persistent to session)
+(NSString *)uuidForSession;

//changes each time the app gets installed (persistent to installation)
+(NSString *)uuidForInstallation;

//changes each time all the apps of the same vendor are uninstalled (this works exactly as identifierForVendor)
+(NSString *)uuidForVendor;

//changes only on system reset, this is the best replacement to the good old udid (persistent to device)
+(NSString *)uuidForDevice;
```

The naming makes the intent explicit. `uuid` is per call. `uuidForKey:` changes each time, but lets you keep more temporary UUIDs in memory at once. `uuidForSession` survives app memory but not a relaunch. `uuidForInstallation` survives relaunch and reboot. `uuidForVendor` is documented as working exactly as identifierForVendor. And `uuidForDevice` is the one that changes only on a system reset.

There is also a category on UIDevice, so the same value is available as an instance method:

```objective-c
#import "UIDevice+FCUUID.h"
[[UIDevice currentDevice] uuid];
```

Choosing a rung is a product decision about what a reinstall should mean to your data. If reinstall should give a fresh user, `uuidForInstallation` is correct. If it should give the same user back, you need `uuidForDevice`.

## The persistence table is the documentation

Most identifier libraries leave you to guess what survives what. This one publishes the matrix, with a tick for yes and a dash for no, across seven events.

| PERSISTS | App memory | App relaunch | Reset Advertising Identifier | App reinstall | System reboot | System upgrade | System reset |
|---|---|---|---|---|---|---|---|
| `uuid` | - | - | - | - | - | - | - |
| `uuidForKey:key` | √ | - | - | - | - | - | - |
| `uuidForSession` | √ | - | - | - | - | - | - |
| `uuidForInstallation` | √ | √ | √ | - | √ | - | - |
| `uuidForVendor` | √ | √ | - | √* | √ | - | - |
| `uuidForDevice` | √ | √ | √ | √ | √ | √ | √** |

Read across and the differences are clear. `uuidForInstallation` does not survive a reinstall, which is the point. `uuidForVendor` survives a reinstall but carries a footnote: it persists only if the user has not uninstalled all apps of the same vendor. `uuidForDevice` is the only one with a tick in the System reset column, and even that carries a condition: it persists only if the user restores a device backup which also includes the keychain data.

That last footnote is the one to notice. `uuidForDevice` is described as changing only on system reset, and the table qualifies that: a device erased without a keychain-bearing backup loses it. For most applications that is acceptable because the user restoring from backup expects their data to come back. For an application where the identifier is tied to a payment method or a licence, it is worth knowing.

## Migration is the feature you will use most

If your app previously stored a UDID or a UUID somewhere, you cannot just start calling `uuidForDevice`. You need to move the old value in, and the library gives you four methods for it, increasing in specificity.

```objective-c
+(NSString *)uuidForDeviceMigratingValue:(NSString *)value commitMigration:(BOOL)commitMigration;
+(NSString *)uuidForDeviceMigratingValueForKey:(NSString *)key commitMigration:(BOOL)commitMigration;
+(NSString *)uuidForDeviceMigratingValueForKey:(NSString *)key service:(NSString *)service commitMigration:(BOOL)commitMigration;
+(NSString *)uuidForDeviceMigratingValueForKey:(NSString *)key service:(NSString *)service accessGroup:(NSString *)accessGroup commitMigration:(BOOL)commitMigration;
```

Each variant searches for an existing UUID or UDID in the KeyChain or in UserDefaults, scoped by the key, service, and access group you pass. The widest variant has no key at all.

The `commitMigration` boolean is the part that makes this usable. Pass `NO` and the method returns the value it found without writing anything, which the README recommends you use first to debug: log the returned value, confirm it is the identifier you expected, and only then commit. Passing `YES` writes it, and after that any future call to `uuidForDevice` returns the migrated value.

Two constraints are stated plainly. Migration is recommended before you call `uuidForDevice` or `uuidsForUserDevices`, because creating the value first would leave nowhere to migrate into. And migration works only if the existing value is a valid UUID, which is where the validation helper comes in:

```objective-c
+(BOOL)uuidValueIsValid:(NSString *)uuidValue;
```

A stored UDID is not a valid UUID, so a value from the old UDID era will not migrate. Check before you rely on it, not after your users have lost their identifiers.

## Two entitlements decide how much of this you get

The requirements list is short and the optional items are the interesting part.

Required: iOS 5.0 or later, ARC enabled, key-value storage enabled under Target / Capabilities / iCloud / Key-value storage, Security.framework, and UICKeyChainStore as a dependency.

Then two optional capabilities that change what the library can do.

With iCloud key-value storage enabled, you can share `uuidsOfUserDevices` values across multiple devices using the same iCloud account. Without it, that method still works but stays local to the one device.

With Keychain sharing enabled, meaning entitlements and a provisioning profile, you can share the same `uuidForDevice` and `uuidsOfUserDevices` values across multiple apps with the same bundle seed.

That second point is answered directly in the FAQ: to share the device UUID between two apps you must have Keychain sharing enabled and your app identifiers must have the same bundle seed. The seed is the part people miss. Two apps with the same team prefix but different bundle identifiers will not see each other's value.

The FAQ also answers the multi-device case directly. Call `uuidForDevice` on two different devices signed into the same iCloud account with iCloud Keychain and you get two different UUIDs, one per device, and `uuidsOfUserDevices` returns a list containing both. So the library does not give you a user identity. It gives you a set of device identities, and it is up to you and your server to decide which device counts as the same person.

## Installation, setup, and the notification hook

Four installation paths are documented. CocoaPods is `pod 'FCUUID'`. Swift Package Manager is File > Swift Packages > Add Package Dependency, then the repository URL, with Up to Next Major at 1.0.0. Carthage takes `github "fabiocaccamo/FCUUID"` in a Cartfile. Manual install means copying the FCUUID folder into your project and manually installing UICKeyChainStore as well, since that dependency is not vendored.

The optional setup is recommended for the `applicationDidFinishLaunchingWithOptions` method, and has three parts. Add an observer for `FCUUIDsOfUserDevicesDidChangeNotification` to be told when the list of user devices changes. Run the migration if you have an existing identifier. And call any class method to enforce iCloud sync.

That notification is the piece that makes the multi-device story work in practice. Without observing it, your app will not notice that the user signed in on another device and added a UUID to the list.

The repository is small and conventional for a CocoaPods library: `FCUUID.podspec`, `FCUUID.xcodeproj/`, the `FCUUID/` source directory, `Package.swift` with `Package.resolved`, and `LICENSE`. The licence is MIT, and there is a donation link at the bottom of the README.

## Where this sits against the platform APIs

The library presents itself as an alternative to UDID and identifierForVendor.

FCUUID's contribution is the middle of the ladder. `uuidForVendor` is explicitly stated to work exactly as identifierForVendor, which means it is a drop-in for the cases where you have outgrown the platform default and want your own storage. `uuidForDevice` is the one that fills the gap UDID left, with the Keychain as the storage and, optionally, iCloud to enumerate a user's devices.

FCUUID provides a device-lifetime identifier, cross-device enumeration, and migration methods for an existing UUID or UDID.

The honest limitation is that the newest tagged release is 1.3.2 from 2021-02-26, with 1.3.1 before it in 2020. The last push was on 2026-04-22, so commits continue, but a library whose public API has not moved in five years is either stable by design or unattended, and for a Keychain-backed persistence library the former is plausible. The iOS 5.0 minimum also dates it.

## Conclusion

Adopt FCUUID if you need a device-scoped identifier that survives reinstall and upgrade without using the withdrawn UDID, and if you have the Keychain entitlements to support it. Do not adopt it as a cross-device user identity on its own, because uuidForDevice is per device and uuidsOfUserDevices requires iCloud key-value storage plus server-side help to be useful. Verify first that the iCloud key-value storage capability is enabled in your target, since without it the cross-device list silently has one entry.

## FAQ

### What is the difference between uuidForDevice and uuidForVendor in FCUUID?

uuidForVendor is documented as working exactly as identifierForVendor and changes when all apps of the same vendor are uninstalled. uuidForDevice is described as changing only on a system reset and as a replacement for UDID, though it persists only if the user restores a backup that includes the keychain data.

### How do I migrate an existing UDID or UUID to FCUUID?

Use one of the uuidForDeviceMigratingValue methods, which search the KeyChain and UserDefaults for an existing value. Pass commitMigration:NO first to inspect what was found by logging the returned value, then commitMigration:YES once you have confirmed it. Migration only works if the existing value is a valid UUID, which you can check with uuidValueIsValid:.

### What entitlements does FCUUID need for cross-device and cross-app UUIDs?

Sharing uuidsOfUserDevices across devices on the same iCloud account needs key-value storage enabled under Target / Capabilities / iCloud. Sharing uuidForDevice across apps needs Keychain sharing enabled with entitlements and a provisioning profile, and both apps must have the same bundle seed.

## Sources

- [fabiocaccamo/FCUUID on GitHub](https://github.com/fabiocaccamo/FCUUID)
- [Issues](https://github.com/fabiocaccamo/FCUUID/issues)
- [License: MIT](https://github.com/fabiocaccamo/FCUUID/blob/master/LICENSE)
- [README](https://github.com/fabiocaccamo/FCUUID/blob/master/README.md)
- [Releases](https://github.com/fabiocaccamo/FCUUID/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/fabiocaccamo-fcuuid
