web-dev-qa-db-fra.com

UIDevice uniqueIdentifier obsolète - Que faire maintenant?

Nous venons de découvrir que la propriété UIDevice uniqueIdentifier est obsolète sous iOS 5 et indisponible dans iOS 7 et versions ultérieures. Aucune méthode ou propriété alternative ne semble être disponible ou à venir.

Bon nombre de nos applications existantes dépendent étroitement de cette propriété pour identifier de manière unique un appareil particulier. Comment pourrions-nous gérer ce problème à l'avenir?

La suggestion de la documentation en 2011-2012 était:

Considérations spéciales

N'utilisez pas la propriété uniqueIdentifier. Pour créer un identifiant unique propre à votre application, vous pouvez appeler la fonction CFUUIDCreate pour créer un UUID et l'écrire dans la base de données par défaut à l'aide de la classe NSUserDefaults.

Toutefois, cette valeur ne sera pas la même si un utilisateur désinstalle et réinstalle l'application.

495
Oliver Pearmain

Un UUID créé par CFUUIDCreate est unique si un utilisateur désinstalle et réinstalle l'application: vous en obtiendrez un nouveau à chaque fois.

Mais vous voudrez peut-être que ce soit et non unique, i. e. il devrait rester identique lorsque l'utilisateur désinstalle et réinstalle l'application. Cela nécessite un peu d'effort, car l'identificateur le plus fiable par périphérique semble être l'adresse MAC. Vous pourriez interroger le MAC et l'utiliser comme UUID.

Edit: Il faut toujours interroger le MAC de la même interface. Je suppose que le meilleur pari est avec en0. Le MAC est toujours présent, même si l'interface n'a pas d'adresse IP/est en panne.

Edit 2: Comme d'autres l'ont déjà souligné, la solution recommandée depuis iOS 6 est - [[UIDevice identifierForVendor] . Dans la plupart des cas, vous devriez pouvoir l'utiliser comme remplacement immédiat de l'ancien -[UIDevice uniqueIdentifier] (mais un UUID créé lors du premier démarrage de l'application correspond à ce que Apple semble veux que tu utilises).

Edit 3: Donc, ce point majeur ne se perd pas dans le bruit des commentaires: n'utilisez pas le MAC en tant qu'UUID, créez un hachage en utilisant le MAC . Ce hachage créera toujours le même résultat à chaque fois, même pour les réinstallations et les applications (si le hachage est effectué de la même manière). Quoi qu'il en soit, de nos jours (2013), cela n'est plus nécessaire, sauf si vous avez besoin d'un identifiant de périphérique "stable" sur iOS <6.0.

Éditer 4: Dans iOS 7, Apple renvoie désormais toujours une valeur fixe lors de l'interrogation du MAC pour contrecarrer spécifiquement le MAC comme base pour un schéma ID . Donc, vous devez maintenant vraiment utiliser - [[UIDevice identifierForVendor] ou créer un UUID par installation.

271
DarkDust

Vous pouvez déjà utiliser votre alternative pour Apple UDID. Le bonhomme Gekitz a écrit la catégorie sur UIDevice qui générera une sorte de UDID basé sur l’adresse MAC du périphérique et l’identifiant du paquet.

Vous pouvez trouver le code sur github

91
Serhii Mamontov

Sur la base du lien proposé par @moonlight, j’ai fait plusieurs tests et cela semble être la meilleure solution. Comme @DarkDust dit que la méthode va vérifier en0 qui est toujours disponible.
Il y a 2 options:
uniqueDeviceIdentifier (MD5 de MAC + CFBundleIdentifier)
et uniqueGlobalDeviceIdentifier (MD5 du MAC), ils retournent toujours les mêmes valeurs.
Ci-dessous les tests que j'ai effectués (avec le vrai appareil):

#import "UIDevice+IdentifierAddition.h"

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

XXXX21f1f19edff198e2a2356bf4XXXX WIFI) UDID
XXXX7dc3c577446a2bcbd77935bdXXXX - (WIFI) GlobalAppUDID

XXXX21f1f19edff198e2a2356bf4XXXX - UDID (3G)
XXXX7dc3c577446a2bcbd77935bdXXXX - (3G) GlobalAppUDID

XXXX21f1f19edff198e2a2356bf4XXXX - UDID (GPRS)
XXXX7dc3c577446a2bcbd77935bdXXXX - GlobalAppUDID (GPRS)

XXXX21f1f19edff198e2a2356bf4XXXX - UDID (mode Plan d'accès)
XXXX7dc3c577446a2bcbd77935bdXXXX - (mode AirPlane) GlobalAppUDID

XXXX21f1f19edff198e2a2356bf4XXXX - (Wi-Fi) après le retrait et la réinstallation de l'application XXXX7dc3c577446a2bcbd77935bdXXXX (Wi-Fi) après le retrait et l'installation de l'application

J'espère que c'est utile.

--- (EDIT:
Comme d'autres l'ont souligné, cette solution sous iOS 7 n'est plus utile, car uniqueIdentifier n'est plus disponible et l'interrogation de l'adresse MAC est désormais toujours renvoyée à 02: 00: 00: 00: 00: 00.

61
Mat

regarde ça,

nous pouvons utiliser le trousseau au lieu de NSUserDefaults class pour stocker UUID créé par CFUUIDCreate.

de cette façon, nous pourrions éviter pour la reconstitution UUID avec la réinstallation et d’obtenir toujours le même UUID pour la même application, même l’utilisateur désinstallera et réinstallera.

UUID sera recréé au moment de la réinitialisation du périphérique par l'utilisateur.

J'ai essayé cette méthode avec SFHFKeychainUtils et cela fonctionne à merveille.

56
ytur

Créez votre propre UUID, puis stockez-le dans le trousseau. Ainsi, il persiste même lorsque votre application est désinstallée. Dans de nombreux cas, il persiste même si l'utilisateur migre entre des périphériques (par exemple, une sauvegarde complète et une restauration sur un autre périphérique).

Effectivement, il devient un identifiant utilisateur unique en ce qui vous concerne. (encore mieux que identifiant de périphérique ).

Exemple:

Je suis en train de définir une méthode personnalisée pour créer un UUID comme:

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

Vous pouvez ensuite l'enregistrer dans KEYCHAIN dès le tout premier lancement de votre application. Ainsi, après le premier lancement, nous pouvons simplement l'utiliser depuis le trousseau, sans avoir à le régénérer. La principale raison d'utiliser le trousseau pour stocker est la suivante: lorsque vous définissez le UUID sur le trousseau, il persiste même si l'utilisateur désinstalle complètement l'application, puis l'installe à nouveau. . Il s’agit donc d’une manière permanente de le stocker, ce qui signifie que la clé sera unique jusqu’à présent.

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

Au lancement d’application, incluez le code suivant:

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

Téléchargez le fichier SSKeychain.m et .h depuis sskeychain et faites glisser le fichier SSKeychain.m et .h vers votre projet et ajoutez "Security.framework" à votre projet. Pour utiliser ensuite l'UUID, utilisez simplement:

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

Peut-être que vous pouvez utiliser:

[UIDevice currentDevice].identifierForVendor.UUIDString

La documentation d'Apple décrit identifierForVender comme suit:

La valeur de cette propriété est la même pour les applications du même fournisseur qui s'exécutent sur le même appareil. Une valeur différente est renvoyée pour les applications du même appareil provenant de différents fournisseurs et pour les applications de différents appareils, quel que soit le fournisseur.

17
diadyne

Vous voudrez peut-être envisager d'utiliser OpenUDID, qui remplacera immédiatement le modèle obsolète UDID.

Fondamentalement, pour correspondre à la UDID, les fonctionnalités suivantes sont requises:

  1. unique ou suffisamment unique (une collision peu probable est probablement très acceptable)
  2. persistance après redémarrage, restauration et désinstallation
  3. disponible sur les applications de différents fournisseurs (utile pour acquérir des utilisateurs via les réseaux CPI) -

OpenUDID remplit ce qui précède et possède même un mécanisme Opt-Out intégré pour une prise en compte ultérieure.

Vérifiez http://OpenUDID.org il pointe vers le GitHub correspondant. J'espère que cela t'aides!

En guise de remarque, je craindrais toute alternative aux adresses MAC. Bien que l’adresse MAC apparaisse comme une solution tentante et universelle, assurez-vous que ce fruit à portée de main est empoisonné. L’adresse MAC est très sensible et Apple risque de rendre obsolète tout accès à celui-ci avant même de dire "SOUMETTRE CETTE APP" ... l’adresse réseau MAC est utilisée pour authentifier certains appareils sur des réseaux privés ( WLAN) ou d’autres réseaux privés virtuels (VPN). .. c'est encore plus sensible que l'ancien UDID!

14
ylechelle

Peut aider: utilisez le code ci-dessous, il sera toujours unique sauf que vous effacez (Formatez) votre appareil.

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

Il semble que pour iOS 6, Apple vous recommande d'utiliser la classe NSUUID .

A partir du message maintenant dans la propriété IDevice docs pour uniqueIdentifier:

Déconseillé dans iOS 5.0. Utilisez la propriété identifierForVendor de cette classe ou la propriété advertisingIdentifier de la classe ASIdentifierManager, selon le cas, ou utilisez la méthode UUID de la classe NSUUID pour créer un UUID et l'écrire dans la base de données par défaut de l'utilisateur.

11
Nate

Je suis sûr que Apple a énervé beaucoup de gens avec ce changement. Je développe une application de comptabilité pour iOS et dispose d'un service en ligne pour synchroniser les modifications apportées sur différents appareils. Le service gère une base de données de tous les périphériques et des modifications à leur transmettre. Par conséquent, il est important de savoir quels appareils sont lesquels. Je garde une trace des périphériques à l'aide de l'identifiant unique UIDevice et voici ce que je pense.

  • Générer un UUID et stocker les valeurs par défaut de l'utilisateur? Pas bon parce que cela ne persiste pas lorsque l'utilisateur supprime l'application. S'ils réinstallent plus tard, le service en ligne ne doit pas créer un nouvel enregistrement de périphérique, cela gaspillerait des ressources sur le serveur et donnerait une liste de périphériques contenant le même fichier deux fois ou plus. Les utilisateurs verraient plus d'un "iPhone de Bob" dans la liste s'ils réinstallaient l'application.

  • Générer un UUID et le stocker dans le trousseau? C'était mon plan, car il persiste même lorsque l'application est désinstallée. Toutefois, lors de la restauration d'une sauvegarde iTunes sur un nouveau périphérique iOS, le trousseau est transféré si la sauvegarde est cryptée. Cela pourrait conduire à deux périphériques contenant le même identifiant si les anciens et les nouveaux périphériques sont tous deux en service. Ceux-ci doivent être répertoriés en tant que deux périphériques dans le service en ligne, même si le nom du périphérique est le même.

  • Générer un hachage l'adresse MAC et l'identifiant du bundle? Cela ressemble à la meilleure solution pour ce dont j'ai besoin. En effectuant un hachage avec l'ID de l'ensemble, l'ID de périphérique généré ne va pas permettre de suivre le périphérique dans les applications et j'obtiens un ID unique pour la combinaison app + périphérique.

Il est intéressant de noter que la propre documentation d’Apple fait référence à la validation de reçus Mac sur l’App Store en calculant un hachage de l’adresse MAC du système, ainsi que de l’identifiant et de la version du kit. Donc, cela semble permis par la politique, si cela passe par l'examen de l'application, je ne le sais pas encore.

11
Mathew Waters

Je suggérerais également de passer de uniqueIdentifier à cette bibliothèque open source (2 catégories simples en réalité) qui utilisent l'adresse MAC du périphérique avec l'identifiant de l'ensemble d'applications pour générer un identifiant unique dans vos applications. qui peut être utilisé comme un remplacement UDID.

Gardez à l'esprit que contrairement à l'UDID, ce nombre sera différent pour chaque application.

Vous devez simplement importer les catégories NSString et UIDevice incluses et appeler [[UIDevice currentDevice] uniqueDeviceIdentifier] comme suit:

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

Vous pouvez le trouver sur Github ici:

IDevice avec UniqueIdentifier pour iOS 5


Voici les catégories (uniquement les fichiers .m - vérifiez le projet github pour les en-têtes):

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
7
chown

Vous pouvez obtenir à partir de ce code: IDevice-with-UniqueIdentifier-for-iOS-5

5
SachinVsSachin

L'adresse MAC peut être usurpée, ce qui rend une telle approche inutile pour lier du contenu à des utilisateurs spécifiques ou implémenter des fonctionnalités de sécurité telles que des listes noires.

Après des recherches plus poussées, il me semble que nous n’avons pas d’alternative appropriée pour le moment. J'espère sérieusement que Apple reconsidérera sa décision.

Ce serait peut-être une bonne idée d’envoyer un e-mail à Apple à propos de ce sujet et/ou de déposer une demande de bogue/fonctionnalité à ce sujet, car ils ne sont peut-être même pas conscients des conséquences pour les développeurs.

4
Toastor

UIDevice identifierForVendor introduit dans iOS 6 fonctionnerait pour vos besoins.

identifierForVendor est une chaîne alphanumérique qui identifie de manière unique un périphérique auprès du fournisseur de l'application. (lecture seulement)

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

La valeur de cette propriété est la même pour les applications du même fournisseur qui s'exécutent sur le même appareil. Une valeur différente est renvoyée pour les applications sur le même appareil provenant de différents fournisseurs, et pour les applications sur différents appareils, quels que soient leurs fournisseurs.

Disponible dans iOS 6.0 et versions ultérieures et déclaré dans UIDevice.h

Pour iOS 5, reportez-vous à ce lien IDevice-with-UniqueIdentifier-for-iOS-5

4
Mahendra Liya

Utilisation de SSKeychain et du code mentionné ci-dessus. Voici le code à copier/coller (ajouter le module 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;

}

4
Komposr

Le code suivant aide à obtenir UDID:

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

C'est le code que j'utilise pour obtenir un identifiant pour iOS 5 et 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];
}
3
Grzegorz Krukowski

iOS 11 a introduit le framework DeviceCheck. Il dispose d'une solution complète pour identifier le périphérique de manière unique.

2
Santosh Botre

À partir de iOS 6, nous avons la classe NSUUID conforme RFC4122

Lien Apple: Apple_ref pour NSUUID

2
DShah

Apple a ajouté un nouveau framework dans iOS 11 appelé DeviceCheck qui vous aidera à obtenir l'identifiant unique très facilement. Lisez ce formulaire pour plus d'informations. https://medium.com/@santoshbotre01/unique-identifier-for-the-ios-devices-590bb778290d

1
Santosh Botre

Vous pouvez utiliser

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

Ce qui est unique pour l'appareil dans toutes les applications.

1
Dhaval

Un moyen efficace d'obtenir l'UDID:

  1. Lancez un serveur Web à l'intérieur de l'application avec deux pages: une doit renvoyer un profil MobileConfiguration spécialement conçu et une autre doit collecter UDID. Plus d'infos ici , ici et ici .
  2. Vous ouvrez la première page de Mobile Safari à partir de l’application, qui vous redirige vers Settings.app vous demandant d’installer le profil de configuration. Une fois le profil installé, UDID est envoyé à la deuxième page Web et vous pouvez y accéder depuis l’application. (Settings.app a tous les droits nécessaires et différentes règles de sandbox).

Un exemple utilisant 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)
    }
}

Voici le contenu de 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>

L'installation du profil échouera (je n'ai pas pris la peine d'implémenter une réponse attendue, voir documentation ), mais l'application obtiendra un UDID correct. Et vous devriez aussi signer le mobileconfig .

1
bzz

Nous pouvons utiliser identifierForVendor pour 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;
}

- Remarque importante ---

UDID et identifierForVendor sont différents: ---

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.
0
HDdeveloper

Si quelqu'un tombe sur cette question, alors que vous recherchez une alternative. J'ai suivi cette approche dans la classe IDManager, il s'agit d'un ensemble de solutions différentes. KeyChainUtil est un wrapper à lire dans le trousseau. Vous pouvez également utiliser le hashed MAC address comme une sorte d’identifiant unique.

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

Pour Swift 3.0 veuillez utiliser le code ci-dessous.

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

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

0
Ankit garg

Apple a masqué l'UDID de toutes les API publiques, à commencer par iOS 7. Tout UDID commençant par FFFF est un faux ID. Les applications "Envoyer UDID" qui fonctionnaient auparavant ne peuvent plus être utilisées pour collecter l'UDID pour les appareils de test. (soupir!)

L'UDID apparaît lorsqu'un périphérique est connecté à XCode (dans l'organiseur) et lorsqu'il est connecté à iTunes (bien que vous deviez cliquer sur 'Numéro de série' pour que l'identificateur s'affiche.

Si vous devez obtenir l'UDID d'un périphérique à ajouter à un profil de provisioning et que vous ne pouvez pas le faire vous-même dans XCode, vous devrez leur expliquer les étapes à suivre pour le copier/coller depuis iTunes.

Y a-t-il un moyen depuis (version iOS 7) d'obtenir l'UDID sans utiliser iTunes sur un PC/Mac?

0
Preet

Pas parfait mais une des meilleures et plus proches alternatives à UDID (dans Swift avec iOS 8.1 et Xcode 6.1):

Générer un UUID aléatoire

let strUUID: String = NSUUID().UUIDString

Et utilisez la bibliothèque KeychainWrapper :

Ajoutez une valeur de chaîne au trousseau:

let saveSuccessful: Bool = KeychainWrapper.setString("Some String", forKey: "myKey")

Récupérer une valeur de chaîne du trousseau:

let retrievedString: String? = KeychainWrapper.stringForKey("myKey")

Supprimer une valeur de chaîne du trousseau:

let removeSuccessful: Bool = KeychainWrapper.removeObjectForKey("myKey")

Cette solution utilise le trousseau. Ainsi, l'enregistrement stocké dans le trousseau sera conservé même après la désinstallation et la réinstallation de l'application. La seule façon de supprimer cet enregistrement consiste à réinitialiser tout le contenu et les paramètres de l'appareil. C'est pourquoi j'ai mentionné que cette solution de substitution n'est pas parfaite mais reste l'une des meilleures solutions de remplacement d'UDID sur iOS 8.1 avec Swift.

0
King-Wizard

J'avais aussi un problème et la solution est 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;
0
Ahmet Kazim Günay
+ (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;
}
0
mahesh chowdary