UIDevice uniqueIdentifierは非推奨-今何をすべきか?


501

それはちょうどことを明るみに出たUIDevice UNIQUEIDENTIFIERプロパティは推奨されませんのiOS 5とiOS 7以上使用できません。代替方法またはプロパティが利用可能または近日公開されるようには見えません。

既存のアプリの多くは、特定のデバイスを一意に識別するためにこのプロパティに強く依存しています。今後、この問題にどのように対処できるでしょうか。

2011-2012年のドキュメントからの提案は次のとおりです。

特別な考慮事項

uniqueIdentifierプロパティは使用しないでください。アプリに固有の一意の識別子を作成するには、CFUUIDCreate関数を呼び出してを作成UUIDし、NSUserDefaultsクラスを使用してそれをデフォルトデータベースに書き込むことができます。

ただし、ユーザーがアプリをアンインストールして再インストールした場合、この値は同じにはなりません。


1
まだuniqueIdentifierを使用しているアプリの場合、iOS7はFFFFFFFF + identifierForVendorを返すようになりました。
Rhythmic Fistman 2013

運が良ければ、アプリがプッシュ通知を使用する場合、
Apple

@CalinChituユーザーがプッシュ通知を受け入れない場合でも、そのユーザーのpushIDを取得しますか?
Chase Roberts

回答:


272

によって作成されたUUID CFUUIDCreate 、ユーザーがアプリをアンインストールして再インストールした場合に一意になります。毎回新しいUUID を取得します。

ただし、一意でなくてもかまいません。つまり、ユーザーがアプリをアンインストールして再インストールしたときも同じままにする必要があります。最も信頼できるデバイスごとの識別子はMACアドレスのように見えるため、これには少し労力が必要です。MACクエリして、それをUUIDとして使用できます

編集:もちろん、同じインターフェイスのMACを常に照会する必要があります。最善の策はであると思いen0ます。インターフェイスにIPがなくても、MACは常に存在します。

編集2:他の人が指摘したように、iOS 6以降の推奨ソリューションは-[UIDevice identifierForVendor]です。ほとんどの場合、それを古いもののドロップイン置換として使用できるはずです-[UIDevice uniqueIdentifier](ただし、アプリの初回起動時に作成されるUUIDは、Appleが使用してほしいものです)。

編集3:したがって、この主要なポイントがコメントノイズで失われることはありません。UUIDとしてMACを使用せず、MACを使用してハッシュを作成してください。そのハッシュは、再インストールやアプリ全体でさえ、常に同じ結果を作成します(ハッシュが同じ方法で行われている場合)。とにかく、今日(2013)iOS 6.0で「安定した」デバイス識別子が必要な場合を除いて、これはもう必要ありません。

編集4: iOS 7では、MACをクエリすると、IDスキームのベースとして MACを明確に阻止するために、Appleは常に固定値を返すようになりました。したがって、実際には-[UIDevice identifierForVendor]を使用するか、インストールごとのUUIDを作成する必要があります。


8
ユーザーがWifi経由で接続しているかどうかに応じて、MACアドレスは変わりませんか?
Oliver Pearmain

1
@DarkDust:ただし、wifiからセルラーモデムに切り替えるとアクティブインターフェイスが変わるため、アクティブインターフェイスのMACアドレスも変わるはずです。あなたは常にMACを取得するために、特定のインタフェースを選択しない限り、
user102008

3
@ロジャー・ノーラン:他の人の回答を編集したり、元の作者からのもののように見えるものを追加したりしないでください。ありがとう。
DarkDust 2013年

2
@RogerNolan投稿がコミュニティの回答でない限り、編集は間違いなどを修正するためであり、新しいものを追加するためではありません。特典を獲得するのには理由があります。私があなたの答えを編集してBSを書くと想像してください。人々はあなたがそれを書いたと思います。:-)しかし、編集が行われたことは通知されません。偶然発見しただけです。
DarkDust 2013

3
AppleはハッシュされたMACを使用するアプリを拒否するようになりました。
Idan

91

Appleの代替案をUDIDすでに使用できます。親切な男gekitzは、デバイスのMAC アドレスとバンドルID UIDeviceUDID基づいて何らかの種類を生成するカテゴリを作成しました。

あなたはgithubでコードを見つけることができます


3
この実装は、AppleのuniqueIdのように、再インストール全体でデバイスに対して一意(MACアドレス)ですが、プライバシーも尊重し、アプリケーションに対しても一意です(bundleIdも使用)... AppleがAPIに含める必要があるimhoが必要です。 ..代替手段なしで非推奨にする代わりに。
Vincent Guerci、2011

8
それは、広告条項で古いスタイルのbsdライセンスを使用していますが、残念です。
jbtule 2009

8
現在この投稿を見つけている人のために、jbtu​​leによる上記のコメント以降、ライセンスが変更されました。
James

1
:このコメントをコミットし、そのままライブラリは深刻なプライバシーのリークの問題を提起して使用すべきではないで説明したように
ウィル

15
iOS 7以降、02:00:00:00:00:00デバイスでMACアドレスを要求すると、システムは常に値を返します。ここで確認してください:developer.apple.com/library/prerelease/ios/releasenotes/General/...
Hejazi

61

@moonlightによって提案されたリンクに基づいて、私はいくつかのテストを行いましたが、それが最良の解決策のようです。@DarkDustが言うように、メソッドen0は常に利用可能かどうかをチェックします。(MAC + CFBundleIdentifierのMD5 ) と(MACのMD5 )の
2つのオプションがあります。これらは常に同じ値を返します。 私が行ったテストの下(実際のデバイスで):
uniqueDeviceIdentifier
uniqueGlobalDeviceIdentifier

#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モード)UDID
XXXX7dc3c577446a2bcbd77935bdXXXX-(AirPlaneモード)GlobalAppUDID

XXXX21f1f19edff198e2a2356bf4XXXX-(Wi-Fi)アプリを削除して再インストールした後XXXX7dc3c577446a2bcbd77935bdXXXX(Wi-Fi)をアプリを削除してインストールした後

お役に立てれば幸いです。

編集:
他の人が指摘したように、iOS 7のこのソリューションはuniqueIdentifier利用できなくなったため、もはや有用ではなく、MACアドレスのクエリは常に02:00:00:00:00:00を返します


13
これはiOS7では機能しません。AppleはMACアドレスの使用を排除します。
サリムシッド2013

@SarimSidd現在のところ、iOS 7に関する情報はNDAに基づいているため、ここでは説明できません。
マット

57

これをチェックして、

NSUserDefaultsクラスの代わりにキーチェーンを使用して、UUIDによって作成されたストアを作成できCFUUIDCreateます。

この方法を使用するUUIDと、再インストールによる再作成を回避でき、UUIDユーザーがアンインストールして再インストールした場合でも、同じアプリケーションで常に同じものを取得できます。

UUID ユーザーがデバイスをリセットしたときに再作成されます。

私はSFHFKeychainUtilsでこの方法を試しましたが、それは魅力のように機能します。


33
このメソッドは、UDIDの確実な代替品です。また、デバイスの形式(たとえば、デバイスが所有者を変更した場合)に基づいて識別子を再作成するという追加の利点もあります。ただし、ユーザーがバックアップを暗号化すると、キーチェーンを他のデバイスに復元できることに注意してください。これにより、複数のデバイスが同じUUIDを共有する場合があります。これを回避するには、キーチェーンアイテムのアクセシビリティをに設定しますkSecAttrAccessibleAlwaysThisDeviceOnly。これにより、UUIDが他のデバイスに移行されなくなります。他のアプリからUUIDにアクセスするには、kSecAttrAccessGroupキーを使用します。
Jeevan Takhar 2012

UUIDをキーチェーンに格納するために正確に(どのキーを)使用することになっていますか?
lostintranslation 2014

おっと!リンクが壊れている
COVID19

48

独自のUUIDを作成して、キーチェーンに保存します。そのため、アプリがアンインストールされても保持されます。多くの場合、ユーザーがデバイス間で移行した場合でも(たとえば、完全バックアップと別のデバイスへの復元)も持続します。

事実上、それはあなたが関係している限り、一意のユーザー識別子になります。(デバイス識別子よりも優れています)。

例:

UUIDas を作成するためのカスタムメソッドを定義しています:

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

その後KEYCHAIN、アプリの最初の起動時に保存できます。そのため、最初の起動後、キーチェーンから簡単に使用でき、再生成する必要はありません。キーチェーンを使用して保存する主な理由は、をキーチェーンに設定するUUIDと、ユーザーがアプリを完全にアンインストールしてから再度インストールしても保持されます。。したがって、これはそれを永続的に保存する方法です。つまり、キーは常に一意になります。

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

アプリケーションの起動時に、次のコードを含めます。

 // 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と.hファイルをsskeychainからダウンロードし、SSKeychain.mと.hファイルを プロジェクトにドラッグして、プロジェクトに「Security.framework」を追加します。後でUUIDを使用するには、次のコマンドを使用します。

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

identifierForVendorが機能しているため、完全には機能しません。場合によっては、nilまたは0x0を返すことがあります。このメソッドは完全に機能しているようです
CReaTuS 2013

3
アンインストール/再インストールのサイクル後にiOS7でこれが機能していることを確認した人+ Appleアプリの提出を確認した人はいますか?
mindbomb 2013年

私はこのソリューションを使い始めました。2つのデバイスでいくつかのテスト(再構築、再インストール、デバイスのシャットダウン)を行ったところ、IDが同じであることがわかりました。iOS 10.3。
deko

16

おそらくあなたは使うことができます:

[UIDevice currentDevice].identifierForVendor.UUIDString

Appleのドキュメントでは、identifierForVenderを次のように説明しています。

このプロパティの値は、同じデバイスで実行されている同じベンダーのアプリでも同じです。ベンダーが異なる同じデバイス上のアプリと、ベンダーに関係なく異なるデバイス上のアプリの場合、異なる値が返されます。


最近まで誰もこれを取り上げなかったのは奇妙です...そして今、私はそれがiOS 6で新しくなっているのを目にしています
James Boutcher

1
ユーザーがiosを更新したり、新しいiosをインストールしたりすると、identifierForVendorの値が変更されるか、同じままになりますか?
スニルZalavadiya 2013

1
同じベンダーのすべてのアプリを削除すると、この値は変更されます。
Mitesh Khatri 2013

14

OpenUDID廃止予定ののドロップイン代替品であるwhichの使用を検討してUDIDください。

基本的に、と一致させるUDIDには、次の機能が必要です。

  1. ユニークまたは十分にユニーク(低確率の衝突はおそらく非常に受け入れられます)
  2. 再起動、復元、アンインストール後の永続性
  3. さまざまなベンダーのアプリで利用可能(CPIネットワーク経由でユーザーを獲得するのに便利)-

OpenUDID 上記を満たし、後で検討するためのオプトアウトメカニズムが組み込まれています。

対応するGitHubを指しているhttp://OpenUDID.orgを確認してください。お役に立てれば!

余談ですが、私は代替のMACアドレスを避けています。MACアドレスは魅力的で普遍的な解決策のように見えますが、この垂れ下がった果物が毒されていることを確認してください。MACアドレスは非常に機密性が高く、Appleは「このアプリを送信」と言う前にこのアドレスへのアクセスを廃止する可能性があります... MACネットワークアドレスは、プライベートLAN(WLAN)または他の仮想プライベート上の特定のデバイスを認証するために使用されますネットワーク(VPN)。..以前のUDIDよりもさらに敏感です!


私はこれがどのように機能するのか本当に知りたいですか?コードはObjective-Cで記述されていますが、上記の要件に適合する優れたソリューションは他にないので、このフレームワークの違いは何ですか?このフレームワークが使用しているソリューションは、ここに提案された回答として投稿することもできます...
jake_hetfield

私は同意します-ほとんどの場合そうではありませんが、MACアドレスも手動で構成できます(「複製」)。私はUDIDでDに抗議しなければなりません。これはデバイスIDではなく、UUID(Universally Unique Identifier)です。デバイスIDは、ROMの各デバイスに工場からAppleによってスタンプされます。
ジェイイマーマン

iOS7に最適なソリューションは、デバイスを一意に識別するために実際に必要なことも行います
vishal dharankar 2014年

1
OpenUDIDは非推奨であり、使用はお勧めしません
mkll

11

Appleはこの変更で多くの人を悩ませたに違いない。私はiOS用の簿記アプリを開発し、さまざまなデバイスで行われた変更を同期するためのオンラインサービスを持っています。サービスは、すべてのデバイスとそれらに伝達する必要がある変更のデータベースを維持します。したがって、どのデバイスがどのデバイスであるかを知ることが重要です。私は、UIDevice uniqueIdentifierを使用してデバイスを追跡しています。その価値について、私の考えを次に示します。

  • UUIDを生成してユーザーのデフォルトに保存しますか?これは、ユーザーがアプリを削除しても持続しないため、問題です。後で再度インストールする場合、オンラインサービスが新しいデバイスレコードを作成しないようにしてください。これにより、サーバー上のリソースが無駄になり、同じものを含むデバイスのリストが2回以上表示されます。アプリを再インストールした場合、ユーザーには複数の「Bob's iPhone」が表示されます。

  • UUIDを生成してキーチェーンに保存しますか?アプリがアンインストールされても持続するため、これは私の計画でした。ただし、iTunesバックアップを新しいiOSデバイスに復元する場合、バックアップが暗号化されているとキーチェーンが転送されます。これにより、古いデバイスと新しいデバイスの両方が稼働している場合、2つのデバイスに同じデバイスIDが含まれる可能性があります。デバイス名が同じであっても、これらはオンラインサービスで2つのデバイスとしてリストされます。

  • MACアドレスとバンドルIDのハッシュを生成しますか?これは、私が必要としているものに最適なソリューションのようです。バンドルIDでハッシュすることにより、生成されたデバイスIDでは、デバイスをアプリ全体で追跡できなくなり、アプリとデバイスの組み合わせの一意のIDが取得されます。

興味深いことに、Apple自身のドキュメントは、システムのMACアドレスとバンドルIDとバージョンのハッシュを計算することによってMac App Storeの領収書を検証することを言及しています。したがって、これはポリシーで許容されるようです。アプリのレビューを通過するかどうかはまだわかりません。


10
2番目のポイントで説明した状況を回避するには、キーチェーンアイテムのアクセシビリティをに設定しますkSecAttrAccessibleAlwaysThisDeviceOnly。これにより、バックアップが暗号化されている場合でも、UUIDが他のデバイスに復元されなくなります。
Jeevan Takhar

これは確かに私が何度も見た行動です。たとえば、iPhoneをGoogle Syncに登録します。それから私は新しいiPhoneを手に入れ、それを登録し、出来上がり-同期設定に2台のiPhoneがリストされました。
ジェイイマーマン

11

iOS 6では、NSUUIDクラスを使用することをお勧めします。

プロパティのUIDeviceドキュメントにあるメッセージからuniqueIdentifier

iOS 5.0では非推奨。代わりに、必要に応じて、このクラスのidentifierForVendorプロパティまたはASIdentifierManagerクラスのAdvertisingIdentifierプロパティを使用するか、NSUUIDクラスのUUIDメソッドを使用してUUIDを作成し、それをユーザーデフォルトデータベースに書き込みます。


10

以下のコードを使用すると、デバイスを消去(フォーマット)する以外は常に一意になります。

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

1
私はこのコードを使用しました。しかし、アプリを削除して再度インストールすると、新しいIDが取得されました
Durgaprasad '30年

1
堅牢な方法が必要ない場合、これは簡単な解決策です。私は今、自分のアプリでそれを使用しています。
ルーベンL.

@Durgaprasad:ベンダーに依存しているため、常に変更されます。次に例を示します。1. bundleidenedifier:com.abcd.com =>でアプリをインストールしている場合は、変更されます。2. bundleidenedifierで2つのアプリをインストールしている場合:com.abcd.com =>変更されません(1つのアプリを保持します)
Ashvin Ajadiya

7

またuniqueIdentifierこのオープンソースライブラリに変更することをお勧めします UDIDの代替として使用することができ、アプリケーション内で一意のIDを生成するために、アプリケーションのバンドル識別子とともに、デバイスのMACアドレスを利用(実際に2つのシンプルなカテゴリ)。

UDIDとは異なり、この数はすべてのアプリで異なることに注意してください。

含まれNSStringているUIDeviceカテゴリとカテゴリをインポートして、次の[[UIDevice currentDevice] uniqueDeviceIdentifier]ように呼び出すだけです。

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

ここのGithubで見つけることができます:

iOS 5のUniqueIdentifierを使用したUIDevice


ここにカテゴリがあります(.mファイルのみ-ヘッダーについてはgithubプロジェクトを確認してください):

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
iOS 7以降、AppleはMACアドレスの定数値を返します。それは完全に理にかなっています。MACアドレスは機密情報です。
ロベルト


4

MACアドレスはスプーフィングされる可能性があるため、コンテンツを特定のユーザーに結び付けたり、ブラックリストなどのセキュリティ機能を実装したりするには、このようなアプローチは役に立たなくなります。

さらなる調査の結果、現時点では適切な代替手段がないままになっているように見えます。Appleが彼らの決定を再考することを真剣に願っています。

多分彼らは開発者にとっての完全な結果に気づいていないかもしれないので、多分彼らはこのトピックについてAppleに電子メールを送り、そして/またはこれについてバグ/機能要求を提出することは良い考えでしょう。


13
有効なポイントですが、ジェイルブレイクされた電話でUUIDがスプーフィング/スウィズルされる可能性があるため、技術的には既存の[UIDevice uniqueIdentifier]にも同様に欠陥があります。
Oliver Pearmain

3
サーバー上でいつでも識別子を作成してデバイスに保存できます。これがほとんどのアプリケーションが行う方法です。iOSプログラマーに特別なものが必要な理由がわかりません。
13:07のスルタン

1
@SulthanはiOSでは機能しません。アプリをアンインストールするとすべてのデータが失われるため、一意のデバイス識別子をそのように保証することはできません。
lkraider 2012

4
キーチェーンに保存した場合はそうではありません。とにかく、これが問題であるアプリを見たことがありません。アプリとデータが削除されている場合、同じデバイス識別子は必要ありません。ユーザーを特定したい場合は、メールで尋ねます。
スルタン

iOSの新しいリリースでは、MACアドレスアクセスもAppleによって禁止されています。
Ans

4

UIDevice identifierForVendor iOS 6で導入されたあなたの目的のために動作します。

identifierForVendorアプリのベンダーがデバイスを一意に識別する英数字の文字列です。(読み取り専用)

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

このプロパティの値は、同じデバイスで実行されている同じベンダーのアプリでも同じです。異なるベンダーの同じデバイス上のアプリと、ベンダーの異なるデバイス上のアプリの場合、異なる値が返されます。

iOS 6.0以降で利用可能で宣言 UIDevice.h

iOS 5の場合は、このリンクを参照してください。UIDevice-with-UniqueIdentifier-for-iOS-5


4

上記のSSKeychainとコードを使用します。コピー/貼り付けするコードは次のとおりです(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;

}


3

次のコードは、UDIDの取得に役立ちます。

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

3

これは、iOS 5とiOS 6、7の両方のIDを取得するために使用しているコードです。

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

コンパイラの警告はどうしますPerformSelector may cause a leak because its selector is unknownか?
バジルブルク14

Appleが拒否するため、この目的でAdvertisingIdentifierを使用することはできません。さらに詳しい情報:techcrunch.com/2014/02/03/...
codeplasma


2

iOS 11はDeviceCheckフレームワークを導入しました。デバイスを一意に識別するための完全なソリューションを備えています。


1

UDIDを取得するための実用的な方法:

  1. 2ページのアプリ内でWebサーバーを起動します。1つは特別に細工されたMobileConfigurationプロファイルを返し、もう1つはUDIDを収集する必要があります。詳細はこちらこちらこちら
  2. アプリ内からMobile Safariの最初のページを開くと、設定プロファイルのインストールを要求するSettings.appにリダイレクトされます。プロファイルをインストールすると、UDIDが2番目のWebページに送信され、アプリ内からアクセスできます。(Settings.appには、必要なすべての資格とさまざまなサンドボックスルールがあります)。

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

内容は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>

プロファイルのインストールは失敗しますが(予想される応答を実装する気になりませんでした。ドキュメントを参照してください)、アプリは正しいUDIDを取得します。また、mobileconfigに署名する必要があります。


1

Swift 3.0の場合、以下のコードを使用してください。

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

1
iOS 11はDeviceCheckフレームワークを導入しました。デバイスを一意に識別するための完全なソリューションを備えています。
Santosh Botre 2017年

1

使用できます

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

これは、すべてのアプリケーションでデバイスに固有です。


1

Appleは、iOS 11にDeviceCheckと呼ばれる新しいフレームワークを追加しました。これにより、一意の識別子を非常に簡単に取得できます。詳細はこちらのフォームをご覧ください。 https://medium.com/@santoshbotre01/unique-identifier-for-the-ios-devices-590bb778290d


でもインターネット接続が必要ですね。
Nik Kov

はい、インターネット接続が必要です。
Santosh Botre

0

誰かがこの質問に出くわした場合、代替案を探しています。私はIDManagerクラスでこのアプローチに従いました。これは、さまざまなソリューションからのコレクションです。KeyChainUtilは、キーチェーンから読み取るラッパーです。hashed MAC addressを一意の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;
}

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

ios7にはidentifierForVendorを使用できます。

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

- 重要な注意点 - -

UDIDとidentifierForVendorは異なります:---

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.

本気ですか ?iOS7にidentifierForVendorを使用できますか?
エイビス

0

Appleは、UDIDをiOS 7以降、すべてのパブリックAPIから隠しています。FFFFで始まるUDIDはすべて偽のIDです。以前機能していた「Send UDID」アプリを使用して、テストデバイスのUDIDを収集することはできなくなりました。(はぁ!)

UDIDは、デバイスが(オーガナイザー内で)XCodeに接続されている場合、およびデバイスがiTunesに接続されている場合に表示されます(ただし、「シリアル番号」をクリックして識別子を表示する必要があります。

デバイスのUDIDを取得してプロビジョニングプロファイルに追加する必要があり、XCodeでそれを自分で実行できない場合は、iTunesからデバイスをコピー/貼り付ける手順を実行する必要があります。

(iOS 7のリリース以降)PC / MacでiTunesを使用せずにUDIDを取得する方法はありますか?


0

私にもいくつかの問題があり、解決策は簡単です:

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

完璧ではありませんが、UDIDの最良かつ最も近い代替手段の1つです(iOS 8.1およびXcode 6.1を使用するSwiftの場合):

ランダムなUUIDの生成

let strUUID: String = NSUUID().UUIDString

そして、KeychainWrapperライブラリを使用します。

文字列値をキーチェーンに追加します。

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

キーチェーンから文字列値を取得します。

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

キーチェーンから文字列値を削除します。

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

このソリューションはキーチェーンを使用するため、アプリをアンインストールして再インストールした後でも、キーチェーンに保存されたレコードは保持されます。このレコードを削除する唯一の方法は、デバイスのすべてのコンテンツと設定をリセットすることです。そのため、この置換のソリューションは完璧ではありませんが、Swiftを使用したiOS 8.1でのUDIDの代替の最良のソリューションの1つであり続けると述べました。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.