iOS は UUID を取得し、キーチェーンを使用してそれを保存します

UDID は非推奨となり、UUID がデバイスの一意の識別子として使用されます。UUID を取得した後、NSUserDefaults を使用して保存した場合、プログラムをアンインストールして再インストールすると、取得される UUID は以前と異なります。キーチェーン ストレージを使用すると、プログラムをアンインストールして再インストールしても UUID が変更されないことが保証されます。ただし、マシンがフラッシュされたり、システムがアップグレードされたりすると、UUID は引き続き変更されます。しかし、これが今のところ最善の解決策であることに変わりはありません


1. 新しいプロジェクトを作成し、バンドル ID を確認します。このバンドル ID は、実機を使用してテストする場合の証明書のバンドル ID と一致する必要があります。

(間違いなく便利) iOS は UUID を取得し、キーチェーンを使用してそれを保存します

たとえば、私のものは house.xianrou.xianrou です。


2.ターゲット - 機能 - キーチェーン共有 - オン


(間違いなく便利) iOS は UUID を取得し、キーチェーンを使用してそれを保存します

 


(間違いなく便利) iOS は UUID を取得し、キーチェーンを使用してそれを保存します

このステップの主な目的は、キーチェーン共有をオンにして、灰色のオフから青色のオンに変更することです。

オープン後の変更点は以下の通りです。


(間違いなく便利) iOS は UUID を取得し、キーチェーンを使用してそれを保存します



(間違いなく便利) iOS は UUID を取得し、キーチェーンを使用してそれを保存します

左側のディレクトリにEntitlements ファイルが自動的に生成されるため、自分で作成する必要はありません。


つまり、バンドル識別子の最初の要素、キーチェーン共有のキーチェーン グループ、および資格ファイルのキーチェーン アクセス グループは、上の図に示す一貫性を維持する必要があります。

セットアップが完了したらプログラムを実行し、問題がなければ次のステップに進んでください。


3.uuidクラスとキーチェーンクラス

Apple のキーチェーン メソッドはクラッシュし、少し複雑であるため、uuid を 1 つだけ保存する場合は、次の簡単なメソッドを使用できます。

(これは、他の人からコピーして変更した私自身の Baidu キーチェーンでもあります)

UUID.h

#import  山括弧 ( Foundation/Foundation.h )


@interface UUID : NSObject


+(NSString *)getUUID;


 

@end


UUID.m


#import "UUID.h"

#import "KeyChainStore.h"



@implementation UUID


+(NSString *)getUUID

{

    NSString * strUUID = (NSString *)[KeyChainStore load:@"com.company.app.usernamepassword"];

    

    //首次执行该方法时,uuid为空

    if ([strUUID isEqualToString:@""] || !strUUID)

    {

        //生成一个uuid的方法

        CFUUIDRef uuidRef = CFUUIDCreate(kCFAllocatorDefault);

        

        strUUID = (NSString *)CFBridgingRelease(CFUUIDCreateString (kCFAllocatorDefault,uuidRef));

   

        //将该uuid保存到keychain

        [KeyChainStore save:KEY_USERNAME_PASSWORD data:strUUID];

        

    }

    return strUUID;

}

 

@end


KeyChainStore.h


#import 尖括号(Foundation/Foundation.h


@interface KeyChainStore : NSObject


+ (void)save:(NSString *)service data:(id)data;

+ (id)load:(NSString *)service;

+ (void)deleteKeyData:(NSString *)service;

 

@end


KeyChainStore.m

#import "KeyChainStore.h"



@implementation KeyChainStore


+ (NSMutableDictionary *)getKeychainQuery:(NSString *)service {

    return [NSMutableDictionary dictionaryWithObjectsAndKeys:

            (id)kSecClassGenericPassword,(id)kSecClass,

            service, (id)kSecAttrService,

            service, (id)kSecAttrAccount,

            (id)kSecAttrAccessibleAfterFirstUnlock,(id)kSecAttrAccessible,

            nil];

}


+ (void)save:(NSString *)service data:(id)data {

    //Get search dictionary

    NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];

    //Delete old item before add new item

    SecItemDelete((CFDictionaryRef)keychainQuery);

    //Add new object to search dictionary(Attention:the data format)

    [keychainQuery setObject:[NSKeyedArchiver archivedDataWithRootObject:data] forKey:(id)kSecValueData];

    //Add item to keychain with the search dictionary

    SecItemAdd((CFDictionaryRef)keychainQuery, NULL);

}


+ (id)load:(NSString *)service {

    id ret = nil;

    NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];

    //Configure the search setting

    //Since in our simple case we are expecting only a single attribute to be returned (the password) we can set the attribute kSecReturnData to kCFBooleanTrue

    [keychainQuery setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData];

    [keychainQuery setObject:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit];

    CFDataRef keyData = NULL;

    if (SecItemCopyMatching((CFDictionaryRef)keychainQuery, (CFTypeRef *)&keyData) == noErr) {

        @try {

            ret = [NSKeyedUnarchiver unarchiveObjectWithData:(__bridge NSData *)keyData];

        } @catch (NSException *e) {

            NSLog(@"Unarchive of %@ failed: %@", service, e);

        } @finally {

        }

    }

    if (keyData)

        CFRelease(keyData);

    return ret;

}


+ (void)deleteKeyData:(NSString *)service {

    NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];

    SecItemDelete((CFDictionaryRef)keychainQuery);

}


 

@end


将这两个类添加到工程中

4.新建一个pch文件,然后pch文件的内容如下:


#ifndef PrefixHeader_pch

#define PrefixHeader_pch


#define  KEY_USERNAME_PASSWORD @"com.company.app.usernamepassword"

#define  KEY_USERNAME @"com.company.app.username"

#define  KEY_PASSWORD @"com.company.app.password"


#endif


pch文件的创建方法可参考:http://blog.csdn.net/huang2009303513/article/details/40375235
有可能会在填Prefix Header 即pch文件的路径那里报错,最近又学习到一种更好的方式$(SRCROOT)/$(PROJECT_NAME)/PrefixHeader.pch,其中$(PROJECT_NAME)是相对工程名,比上面的方法更便捷.


5.在viewcontroller.m里面执行如下代码

  NSString * uuid= [UUID getUUID];

  NSLog(@"uuid=%@",uuid);

  得到的uuid类似于这种
  uuid=19AAB430-9CB8-4325-ACC5-D7D386B68960
  
然后卸载掉,再重新运行,看前后得到的uuid是不是一样

転載元: http://blog.sina.com.cn/s/blog_5971cdd00102vqgy.html

おすすめ

転載: blog.csdn.net/baidu_33298752/article/details/51656096