UIDevice uniqueIdentifier kullanımdan kaldırıldı - Şimdi ne yapmalı?


501

O sadece hafif geldi UIDevice uniqueIdentifier özelliği kullanımdan kaldırıldı içinde iOS 5 ve iOS 7'de ve üzeri kullanılamaz. Kullanılabilir veya gelecek alternatif bir yöntem veya özellik yok.

Mevcut uygulamalarımızın çoğu, belirli bir cihazı benzersiz bir şekilde tanımlamak için bu özelliğe sıkı sıkıya bağlıdır. İleride bu sorunu nasıl çözebiliriz?

2011-2012 belgelerinde öneri :

Özel Hususlar

UniqueIdentifier özelliğini kullanmayın. Uygulamanıza özgü benzersiz bir tanımlayıcı oluşturmak için a CFUUIDCreateişlevini oluşturmak üzere işlevi çağırabilir UUIDve NSUserDefaultssınıfı kullanarak varsayılan veritabanına yazabilirsiniz .

Ancak, bir kullanıcı uygulamayı kaldırır ve yeniden yüklerse bu değer aynı olmaz.


1
Halen uniqueIdentifier kullanan uygulamalar için iOS7, kötü yazılmış ve yenilenmeyen abonelik uygulamalarının çoğunu bozan FFFFFFFF + identifierForVendor'ı döndürüyor.
Ritmik Fistman

Şans eseri uygulamanız Push Bildirimleri kullanıyorsa, elmanın push servisinden gönderilen jetonu kullanabilirsiniz, cihaz başına da benzersizdir
Calin Chitu

@CalinChitu Kullanıcı push bildirimlerini kabul etmezse, yine de o kullanıcı için pushID alıyor musunuz?
Chase Roberts

Yanıtlar:


272

Bir UUID tarafından oluşturulan CFUUIDCreate olduğunu yeni bir her zaman alacak: Bir kullanıcı kaldırıp uygulamayı yeniden yüklerse benzersiz.

Ancak benzersiz olmamasını isteyebilirsiniz , yani kullanıcı uygulamayı kaldırıp yeniden yüklediğinde aynı kalmalıdır. Cihaz için en güvenilir tanımlayıcı MAC adresi gibi göründüğünden, bu biraz çaba gerektirir. MAC'yi sorgulayabilir ve UUID olarak kullanabilirsiniz.

Düzenleme: Bir, elbette, aynı arabirimin MAC sorgulamak gerekir. Sanırım en iyi bahis en0. Arayüzde IP / devre dışı olmasa bile MAC daima mevcuttur.

Düzenleme 2: Başkaları tarafından belirtildiği gibi, iOS 6'dan beri tercih edilen çözüm - [UIDevice tanımlayıcıForVendor] . Çoğu durumda, eski -[UIDevice uniqueIdentifier]sürümün yerine yedek olarak kullanabilmeniz gerekir (ancak uygulama ilk kez başlatıldığında oluşturulan bir UUID, Apple'ın kullanmanızı istediği şeydir).

Edit 3: Bu önemli nokta yorum gürültüsünde kaybolmaz: MAC'yi UUID olarak kullanmayın, MAC kullanarak bir karma oluşturun . Bu karma, yeniden yüklemeler ve uygulamalarda bile (karma aynı şekilde yapılırsa) her seferinde aynı sonucu her zaman oluşturur. Her neyse, günümüzde (2013), iOS <6.0'da "kararlı" bir cihaz tanımlayıcısına ihtiyacınız olması dışında bu artık gerekli değildir.

Düzenleme 4: iOS 7'de, Apple artık MAC'ı bir kimlik şemasının temelini MAC olarak engellemek için sorgularken her zaman sabit bir değer döndürüyor . Şimdi - [UIDevice identifierForVendor] kullanmalı veya yükleme başına UUID oluşturmalısınız.


8
Mac adresi, kullanıcının Wifi üzerinden bağlı olup olmamasına bağlı olarak değişmiyor mu?
Oliver Pearmain

1
@DarkDust: ancak wifi'den hücresel modeme geçtiğinizde aktif arayüz değiştiğinden, aktif arayüzün MAC adresi de değişmelidir; MAC'i almak için her zaman belirli bir arabirim seçmediğiniz sürece
user102008

3
@Roger Nolan: Lütfen başkalarının yanıtlarını düzenlemeyin ve orijinal yazardan gelmiş gibi görünen şeyler ekleyin. Teşekkürler.
DarkDust

2
@RogerNolan Gönderi bir topluluk yanıtı olmadığı sürece, düzenlemeler hataları ve bu gibi şeyleri düzeltmek içindir, yeni şeyler eklemek için değildir. Ayrıcalığı kazanmanız için bir neden var. Cevabınızı düzenlediğimi ve bazı BS yazdığımı düşünün, insanlar bunu yazacağınızı düşünecekti. Bunu istiyorum şüphe :-) Ama bildirim alamadım o bir düzenleme sadece kazara öğrendim, oldu.
DarkDust

3
Apple artık karma MAC kullanan uygulamaları reddediyor.
Idan

91

Apple için alternatifinizi UDIDzaten kullanabilirsiniz. Kind guy gekitz , cihaz mac adresine ve paket tanımlayıcısına dayalı bir UIDevicetür üretecek kategori yazdı UDID.

Kodu github'da bulabilirsiniz


3
Bu uygulama, Apple'ın uniqueId gibi yeniden yüklemelerdeki bir cihaz için benzersizdir (MAC adresi), aynı zamanda bir uygulama için de benzersiz olan gizliliğe saygı duyar (ayrıca bundleId kullanın) ... Apple'ın API'larına eklemesi gereken imho olmalıdır. .. herhangi bir alternatif olmadan kullanımdan kaldırmak yerine.
Vincent Guerci

8
Her ne kadar eski stil bsd lisans reklam yan tümcesi ile kullanmasına rağmen, yuck.
jbtule

8
Şimdi bu gönderiyi bulan diğer herkes için, lisans jbtule tarafından yukarıdaki yorumdan bu yana değiştirildi.
James

1
Yorumunu işlemek bu tartışıldığı gibi, kütüphane yumuşayıp poz ciddi gizlilik sızıntısı sorunu olarak-ve kullanılmaması gerekir:
Will

15
İOS 7'den başlayarak 02:00:00:00:00:00, herhangi bir cihazda MAC adresi istediğinde sistem her zaman değeri döndürür . Buraya bakın: developer.apple.com/library/prerelease/ios/releasenotes/General/…
Hejazi

61

@Moonlight tarafından önerilen bağlantıya dayanarak, birkaç test yaptım ve en iyi çözüm gibi görünüyor. @DarkDust'un dediği gibi, yöntem en0hangisinin daima mevcut olduğunu kontrol etmeye gider .
2 seçenek vardır:
uniqueDeviceIdentifier(MAC + CFBundleIdentifier'ın MD5'i)
ve uniqueGlobalDeviceIdentifier( MAC'ın MD5'i ), bunlar her zaman aynı değerleri döndürür.
Yaptığım testlerin altında (gerçek cihazla):

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

XXXX21f1f19edff198e2a2356bf4XXXX - Uygulamayı kaldırdıktan ve yeniden yükledikten sonra (Wi-Fi) Uygulamayı kaldırdıktan ve yükledikten sonra XXXX7dc3c577446a2bcbd77935bdXXXX (Wi-Fi)

Umarım faydalıdır.

EDIT:
Diğerlerinin de işaret ettiği gibi, iOS 7'deki bu çözüm uniqueIdentifierartık kullanılamıyor ve MAC adresi için sorgulama artık her zaman 02: 00: 00: 00: 00: 00 döndürüyor


13
Bu iOS7 üzerinde çalışmaz, Apple MAC adresi kullanımını ortadan kaldırır.
Sarim Sidd

@SarimSidd Şimdilik iOS 7 hakkındaki bilgiler NDA altında, burada tartışamıyoruz.
Mat

57

şuna bir bak,

tarafından oluşturulan NSUserDefaultssaklamak için sınıf yerine Anahtarlık kullanabiliriz .UUIDCFUUIDCreate

bu şekilde UUID, yeniden yükleme ile rekreasyondan kaçınabiliriz ve UUIDaynı uygulama için kullanıcı kaldırma ve yeniden yükleme bile her zaman aynı olabilir .

UUID cihaz kullanıcı tarafından sıfırlandığında yeniden oluşturulur.

Bu yöntemi SFHFKeychainUtils ile denedim ve bir cazibe gibi çalışıyor.


33
Bu yöntem, UDID için sağlam bir alternatiftir. Ayrıca, tanımlayıcıyı cihaz biçiminde yeniden oluşturma avantajına da sahiptir (örneğin, cihaz sahibi değiştirirse). Ancak, kullanıcı yedeklemelerini şifrelerse anahtar zincirinin diğer cihazlara geri yüklenebileceğini unutmamak önemlidir. Bu, birden çok cihazın aynı UUID'yi paylaştığı bir duruma neden olabilir. Bundan kaçınmak için anahtarlık öğenizin erişilebilirliğini olarak ayarlayın kSecAttrAccessibleAlwaysThisDeviceOnly. Bu, UUID'nizin başka bir cihaza taşınmamasını sağlar. UUID'nize diğer uygulamalardan erişmek için kSecAttrAccessGrouptuşunu kullanın.
Jeevan Takhar

UUID'yi anahtarlıkta saklamak için tam olarak nerede (hangi anahtar) kullanmanız gerekiyor?
lostintranslation

Opps! bağlantı bozuk
COVID19

48

Kendi UUID'nizi oluşturun ve daha sonra Anahtarlıkta saklayın. Böylece uygulamanız kaldırıldığında bile devam eder. Çoğu durumda, kullanıcı aygıtlar arasında geçiş yapsa bile devam eder (örn. Tam yedekleme ve başka bir aygıta geri yükleme).

Etkili bir şekilde , size göre benzersiz bir kullanıcı tanımlayıcısı haline gelir . ( cihaz tanımlayıcıdan daha iyi ).

Misal:

Bir UUIDas oluşturmak için özel bir yöntem tanımlıyorum :

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

Daha sonra KEYCHAINuygulamanızın ilk lansmanında saklayabilirsiniz . Böylece, ilk lansmandan sonra, onu anahtarlıktan kullanabiliriz, yeniden oluşturmaya gerek yoktur. Saklamak için Keychain'i kullanmanın ana nedeni: Keychain'i ayarladığınızda UUID, kullanıcı Uygulamayı tamamen kaldırsa ve tekrar yüklese bile devam eder. . Yani, bu onu saklamanın kalıcı bir yolu, yani anahtar tamamen benzersiz olacak.

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

Uygulama başlangıcında aşağıdaki kodu ekleyin:

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

SSKeychain.m ve .h dosyasını sskeychain'den indirin ve SSKeychain.m ve .h dosyasını projenize sürükleyin ve projenize "Security.framework" ekleyin. Daha sonra UUID kullanmak için şunu kullanın:

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

ForForendender çalışıyor bir tanımlayıcı mükemmel değildir çünkü. Bazı durumlarda sıfır veya 0x0 döndürebilirsiniz. Görünüşe göre bu yöntem mükemmel çalışıyor
CReaTuS

3
kimse kaldırma / yeniden yükleme döngüsü + doğrulanmış elma uygulaması gönderme sonra iOS7 üzerinde çalışıyor doğruladı?
mindbomb

Bu çözümü kullanmaya başladım. 2 cihazda yapılan çeşitli testler (yeniden oluşturma, yeniden yükleme, cihazı kapatma) bana kimliğin aynı olduğunu gösterdi. iOS 10.3.
deko

16

Belki şunları kullanabilirsiniz:

[UIDevice currentDevice].identifierForVendor.UUIDString

Apple'ın belgeleri tanıtıcıForVender'ı şu şekilde açıklar:

Bu özelliğin değeri, aynı cihazda çalışan aynı satıcıdan gelen uygulamalar için aynıdır. Aynı cihazdaki farklı satıcılardan gelen uygulamalar ve satıcıdan bağımsız olarak farklı cihazlardaki uygulamalar için farklı bir değer döndürülür.


Kimsenin bunu yakın zamana kadar neden yükseltmediğini merak ediyorum ... Ve şimdi iOS 6'da yeni olduğunu görüyorum
James Boutcher

1
Kullanıcı ios güncellemesi yaparsa ve / veya yeni ios kurarsa identifierForVendor'ın değeri değişecek veya aynı kalacak mı?
Sunil Zalavadiya

1
Aynı tedarikçiden tüm uygulamaları kaldırdıktan sonra bu değer değişecektir.
Mitesh Khatri

14

Kullanımdan OpenUDIDkaldırılanlar için bir yedek yedek olan kullanmayı düşünebilirsiniz UDID.

Temel olarak, UDIDaşağıdakilere uymak için aşağıdaki özellikler gereklidir:

  1. benzersiz veya yeterince benzersiz (düşük olasılıklı bir çarpışma muhtemelen çok kabul edilebilir)
  2. yeniden başlatmalar, geri yüklemeler, yüklemeler arasında kalıcılık
  3. farklı satıcıların uygulamalarında kullanılabilir (CPI ağları üzerinden kullanıcı elde etmek için yararlıdır) -

OpenUDID Yukarıdakileri yerine getirir ve daha sonra değerlendirmek için yerleşik bir Kapsam Dışında Kalma mekanizması vardır.

İlgili GitHub'a işaret ettiği http://OpenUDID.org adresini kontrol edin . Bu yardımcı olur umarım!

Bir yan not olarak, herhangi bir MAC adresi alternatifinden utangaç olurum. MAC adresi cazip ve evrensel bir çözüm gibi görünse de, bu düşük asılı meyvenin zehirlendiğinden emin olun. MAC adresi çok hassas ve "BU APP GÖNDER" diyebilmeniz için Apple bu adrese erişimi çok iyi bir şekilde azaltabilir. ağlar (VPN'ler). .. eski UDID'den bile daha hassas!


Bunun nasıl çalıştığını gerçekten merak ediyorum. Kod Objective-C'de yazılmıştır, ancak yukarıdaki gereksinimlere uyan başka iyi bir çözüm yoktur, bu yüzden bu çerçeveyi farklı kılan nedir? Bu çerçevenin kullandığı çözüm burada önerilen bir cevap olarak da gönderilebilir ...
jake_hetfield

Aynı fikirdeyim - MAC adresi de elle yapılandırılabilir ("klonlanmış"), ancak büyük olasılıkla olmasa da. UDID'de D'yi protesto etmeliyim. Bu bir Aygıt Kimliği değil, bir UUID'dir (Evrensel Olarak Benzersiz Tanımlayıcı). Aygıt Kimliği, ROM'daki her aygıtta fabrikadan Apple tarafından damgalanır.
Jay Imerman

İOS7 için de en iyi çözüm, bir cihazı benzersiz bir şekilde tanımlamak için gerçekten gerekli olan şey
vishal dharankar

1
OpenUDID kullanımdan kaldırıldı ve kullanılması tavsiye edilmez
mkll

11

Eminim Apple bu değişimle birçok insanı rahatsız etmiştir. İOS için bir defter tutma uygulaması geliştiriyorum ve farklı cihazlarda yapılan değişiklikleri senkronize etmek için çevrimiçi bir hizmetim var. Hizmet, tüm cihazların bir veritabanını ve bunlara yayılması gereken değişiklikleri tutar. Bu nedenle hangi cihazların hangileri olduğunu bilmek önemlidir. Ben UIDevice uniqueIdentifier kullanarak cihazları takip ediyorum ve ne için değer, burada benim düşüncelerim.

  • Bir UUID ve kullanıcı varsayılanları depolamak? İyi değil çünkü kullanıcı uygulamayı sildiğinde bu devam etmiyor. Daha sonra tekrar yüklerse, çevrimiçi hizmet yeni bir aygıt kaydı oluşturmamalıdır; bu, sunucudaki kaynakları boşa harcar ve aynı iki veya daha fazla kez içeren aygıtların bir listesini verir. Kullanıcılar, uygulamayı yeniden yüklediklerinde birden fazla "Bob'un iPhone'u" görür.

  • Bir UUID oluşturup anahtarlıkta depolamak mı istiyorsunuz? Uygulama kaldırıldığında bile devam ettiğinden bu benim planımdı. Ancak bir iTunes yedeklemesini yeni bir iOS cihazına geri yüklerken, yedek şifrelenirse anahtarlık aktarılır. Bu, eski ve yeni cihazların ikisi de hizmette ise aynı cihaz kimliğini içeren iki cihaza yol açabilir. Cihaz adı aynı olsa bile bunlar çevrimiçi hizmette iki cihaz olarak listelenmelidir.

  • Bir karma MAC adresi ve paket kimliği oluştur? Bu, ihtiyacım olan şey için en iyi çözüm gibi görünüyor. Paket kimliğiyle karma yaparak, oluşturulan cihaz kimliği cihazın uygulamalar arasında izlenmesini sağlamaz ve uygulama + cihaz kombinasyonu için benzersiz bir kimlik alırım.

Apple'ın kendi belgelerinin , sistem MAC adresinin bir karma değerini ve paket kimliğini ve sürümünü hesaplayarak Mac App Store makbuzlarını doğrulamak anlamına geldiğini belirtmek ilginçtir . Bu yüzden henüz bilmediğim uygulama incelemesinden geçip geçmediği politika tarafından izin verilebilir.


10
İkinci noktanızda açıklanan durumdan kaçınmak için, anahtarlık öğenizin erişilebilirliğini olarak ayarlayın kSecAttrAccessibleAlwaysThisDeviceOnly. Bu, yedekleme şifrelenmiş olsa bile UUID'nizin diğer cihazlara geri yüklenmemesini sağlar.
Jeevan Takhar

Bu aslında birçok kez gördüğüm davranış. Örneğin, iPhone'umu Google Sync için kaydettiriyorum. Sonra yeni bir iPhone aldım, kaydedin ve işte - Şimdi Sync ayarlarımda 2 iPhone'um var.
Jay Imerman

11

Görünüşe göre iOS 6 için Apple, NSUUID sınıfını kullanmanızı tavsiye ediyor .

Şu anda mülk için UIDevice dokümanlarındaki mesajdanuniqueIdentifier :

İOS 5.0'da kullanımdan kaldırıldı. Bunun yerine, bu sınıfın identifierForVendor özelliğini veya ASIdentifierManager sınıfının AdvertisingIdentifier özelliğini kullanın veya bir UUID oluşturmak ve kullanıcı varsayılanları veritabanına yazmak için NSUUID sınıfının UUID yöntemini kullanın.


10

Yardımcı olabilir: Aşağıdaki kodu kullanın, cihazınızı silmeniz (biçimlendirmeniz) dışında her zaman benzersiz olacaktır.

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

1
Bu kodu kullandım. Ancak uygulamayı
sildiğimde

1
sağlam bir yönteme ihtiyacınız yoksa bu basit bir çözümdür. şimdi benim app kullanıyorum.
Reuben L.

@Durgaprasad: satıcıya bağlı olduğu için her zaman değişecektir. Örneğin: 1. bundleidenedifier: com.abcd.com => ile bir uygulama yüklediyseniz, değişecektir. 2. bundleidenedifier ile iki uygulama yüklediyseniz: com.abcd.com => O zaman chnage olmaz (sırasında herhangi bir uygulama tutmak)
Ashvin Ajadiya

7

Ben de arta değişen öneririm uniqueIdentifieriçin bu açık kaynak kütüphanesinde bir UDID yedek olarak kullanılabilir uygulamalarınızda benzersiz bir kimlik oluşturmak için Uygulama Paketi Identifier ile birlikte cihazın MAC adresini kullanır (gerçekten 2 basit kategoriler).

UDID'den farklı olarak bu numaranın her uygulama için farklı olacağını unutmayın.

Sadece dahil edilen NSStringve UIDevicekategorileri içe aktarmanız ve şu şekilde arayın [[UIDevice currentDevice] uniqueDeviceIdentifier]:

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

Github'da burada bulabilirsiniz:

İOS 5 için UniqueIdentifier özellikli UIDevice


Kategoriler aşağıdadır (sadece .m dosyaları - github projesinin başlıkları kontrol edin):

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

3
İOS 7'den itibaren Apple, MAC adresi için sabit bir değer döndürecektir. Mükemmel mantıklı. MAC adresi hassastır.
Roberto


4

MAC adresi sahte olabilir, bu da böyle bir yaklaşımı belirli kullanıcılara içerik bağlamak veya kara listeler gibi güvenlik özelliklerini uygulamak için işe yaramaz hale getirir.

Biraz daha araştırma yaptıktan sonra şu an için uygun bir alternatif olmadan kaldığımız anlaşılıyor. Umarım Apple kararlarını tekrar gözden geçirir.

Belki de bu konuda Apple'a e-posta göndermek ve / veya bu konuda bir hata / özellik isteği göndermek iyi bir fikir olabilir, çünkü belki de geliştiricilerin tam sonuçlarının farkında bile değillerdir.


13
Geçerli bir nokta, ancak UUID, aynı zamanda teknik olarak mevcut [UIDevice uniqueIdentifier] gibi kusurlu bir jailbreak telefon dolandırıcı / swizzled inanıyoruz.
Oliver Pearmain

3
Sunucuda her zaman bir tanımlayıcı oluşturabilir ve cihaza kaydedebilirsiniz. Çoğu uygulama böyle yapar. İOS programcılarının neden özel bir şeye ihtiyaç duyduklarını anlamıyorum.
Sulthan

1
@Sulthan iOS'ta çalışmaz, çünkü bir uygulamayı kaldırırsanız tüm verileri kaybolur, bu nedenle benzersiz bir cihaz tanımlayıcısını bu şekilde garanti etmenin bir yolu yoktur.
lkraider

4
Eğer anahtarlığa kaydederseniz olmaz. Her neyse, bunun bir sorun olduğu bir uygulama görmedim. Uygulama ve veriler silinmişse, aynı cihaz tanımlayıcısına ihtiyacınız yoktur. Kullanıcıyı tanımlamak istiyorsanız, ondan e-posta isteyin.
Sulthan

MAC adresi erişimi, iOS'un yeni sürümünde Apple tarafından da yasaklandı;
Ans

4

UIDevice identifierForVendor iOS 6'da tanıtılanlar sizin amaçlarınız için çalışır.

identifierForVendorbir uygulamayı uygulamanın satıcısına benzersiz şekilde tanımlayan alfasayısal bir dizedir. (Sadece oku)

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

Bu özelliğin değeri, aynı cihazda çalışan aynı satıcıdan gelen uygulamalar için aynıdır. Farklı cihazlardan gelen aynı cihazdaki uygulamalar ve satıcının farklı cihazlarındaki uygulamalar için farklı bir değer döndürülür.

İOS 6.0 ve sonraki sürümlerde kullanılabilir ve UIDevice.h

İOS 5 için, iOS-5 için UniqueIdentifier ile bu UIDevice bağlantısına bakın


4

SSKeychain ve yukarıda belirtilen kodu kullanarak. Kopyalamak / yapıştırmak için kod (SSKeychain modülünü ekleyin):

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

}


3

Aşağıdaki kod UDID almanıza yardımcı olur:

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

3

Bu hem iOS 5 hem de iOS 6, 7 için kimlik almak için kullandığım kod:

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

Derleyici uyarısı hakkında ne yaparsınız PerformSelector may cause a leak because its selector is unknown?
Basil Bourque

Apple bunu reddedeceğinden, bu amaçla AdvertisingIdentifier'ı kullanamazsınız. Daha fazla bilgi: techcrunch.com/2014/02/03/…
codeplasma


2

iOS 11, DeviceCheck çerçevesini tanıttı. Cihazı benzersiz bir şekilde tanımlamak için tam geçirmez bir çözüme sahiptir.


1

UDID almanın çalışma yolu:

  1. Uygulama içinde iki sayfa içeren bir web sunucusu başlatın: biri özel hazırlanmış MobileConfiguration profilini döndürmeli ve diğeri UDID toplamalıdır. Burada , burada ve burada daha fazla bilgi .
  2. Mobil Safari'deki ilk sayfayı uygulamanın içinden açarsınız ve sizi yapılandırma profilini yüklemenizi isteyen Settings.app'ye yönlendirir. Profili yükledikten sonra, UDID ikinci web sayfasına gönderilir ve uygulamaya uygulamanın içinden erişebilirsiniz. (Settings.app gerekli tüm yetkilere ve farklı sanal alan kurallarına sahiptir).

RoutingHTTPServer kullanan bir örnek :

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

İşte içeriği 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>

Profil yüklemesi başarısız olur (beklenen bir yanıtı uygulama zahmetine girmedim, belgelere bakın ), ancak uygulama doğru bir UDID alacak. Ayrıca mobileconfig'i de imzalamanız gerekir .


1

Swift 3.0 için lütfen aşağıdaki kodu kullanın.

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

1
iOS 11, DeviceCheck çerçevesini tanıttı. Cihazı benzersiz bir şekilde tanımlamak için tam geçirmez bir çözüme sahiptir.
Santosh Botre

1

Kullanabilirsiniz

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

Hangi tüm uygulamada cihaz için benzersizdir.



0

Birisi bu soruya rastlarsa, alternatif ararken. IDManagerSınıfta bu yaklaşımı izledim , Bu farklı çözümlerden bir koleksiyon. KeyChainUtil anahtarlıktan okumak için bir sarıcıdır. Ayrıca hashed MAC address, bir tür benzersiz kimlik olarak da kullanabilirsiniz .

/*  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
+ (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

Biz kullanabilirsiniz identifierForVendor , -iOS7 için

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

--Önemli Not ---

UDID ve tanımlayıcı Satıcı farklıdır: ---

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.

Emin misiniz ? ios7 için identifierForVendor kullanabilir miyiz?
Avis

0

Apple, iOS 7'den başlayarak UDID'yi tüm genel API'lardan gizledi. FFFF ile başlayan herhangi bir UDID sahte bir kimliktir. Daha önce çalışmış olan "UDID Gönder" uygulamaları artık test cihazları için UDID toplamak için kullanılamaz. (iç çekmek!)

UDID, bir cihaz XCode'a (ajandada) bağlandığında ve cihaz iTunes'a bağlandığında (Tanımlayıcının görüntülenmesini sağlamak için 'Seri Numarası'nı tıklamanız gerekmesine rağmen) gösterilir.

Bir ön hazırlık profiline eklemek için bir aygıtın UDID'sini almanız gerekiyorsa ve bunu XCode'da kendiniz yapamıyorsanız, bunları iTunes'tan kopyalamak / yapıştırmak için adımlardan geçirmeniz gerekir.

PC / Mac'te iTunes kullanmadan UDID'yi almanın bir yolu var mı (iOS 7'nin sürümü)?


0

Ben de bir sorunum vardı ve çözüm basit:

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

Mükemmel değil ama UDID'ye en iyi ve en yakın alternatiflerden biri (iOS 8.1 ve Xcode 6.1 kullanan Swift'de):

Rastgele bir UUID oluşturma

let strUUID: String = NSUUID().UUIDString

Ve KeychainWrapper kitaplığını kullanın :

Anahtarlıklara bir dize değeri ekleyin:

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

Anahtarlıktan bir dize değeri alın:

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

Bir dize değerini anahtarlıktan kaldırın:

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

Bu çözüm anahtarlığı kullanır, bu nedenle uygulama kaldırılıp yeniden yüklendikten sonra bile anahtarlıkta saklanan kayıt kalıcı olacaktır. Bu kaydı silmenin tek yolu cihazın tüm içeriğini ve ayarlarını sıfırlamaktır. Bu yüzden bu ikame çözümünün mükemmel olmadığını, ancak Swift kullanarak iOS 8.1'de UDID'nin en iyi yedek çözümlerinden biri olduğunu belirtti.


0

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.