iOS 设备的唯一标识符最新

本文介绍了在iOS设备上获取唯一标识符的两种方法:identifierForVendor和advertisingIdentifier。identifierForVendor在app被删除并重新安装后会改变,而advertisingIdentifier用于广告追踪且可能变化。为解决identifierForVendor的不稳定性,可以将首次生成的标识符保存到keyChain中,以确保应用重装后的连续性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

**现在苹果明确的表明你应该使用-[UIDevice identifierForVendor]或是-[ASIdentifierManager advertisingIdentifier]来作为你框架和应用的唯一标示符。坦白的来说,应对这些变化也不是那么的难,见以下代码片段:

NSString *identifierForVendor = [[UIDevice currentDevice].identifierForVendor UUIDString]; 
NSString *identifierForAdvertising = [[ASIdentifierManager sharedManager].advertisingIdentifier UUIDString]; 

每种方法都适配一种特别的用法:
  identifierForVendor对供应商来说是唯一的一个值,也就是说,由同一个公司发行的的app在相同的设备上运行的时候都会有这个相同的标识符。然而,如果用户删除了这个供应商的app然后再重新安装的话,这个标识符就会不一致。
  advertisingIdentifier会返回给在这个设备上所有软件供应商相同的 一个值,所以只能在广告的时候使用。这个值会因为很多情况而有所变化,比如说用户初始化设备的时候便会改变。
由于identifierForVendor删除了这个供应商的app然后再重新安装的话,这个标识符就会不一致,所以要解决这个问题可以把第一次生成的唯一标示符,保存到keyChain(钥匙串)中,当应用被删除后keyChain中的数据还在,下次在从keyChain中取就OK了
废话就讲到这了,下面是代码:

#define KEY_UDID            @"KEY_UDID"  
#define KEY_IN_KEYCHAIN     @"KEY_IN_KEYCHAIN"  

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

@implementation APPIdentificationManage  
singleton_implementation(APPIdentificationManage)  

#pragma mark 获取UUID  
/** 
 *此uuid在相同的一个程序里面-相同的vindor-相同的设备下是不会改变的 
 *此uuid是唯一的,但应用删除再重新安装后会变化,采取的措施是:只获取一次保存在钥匙串中,之后就从钥匙串中获取 
 **/  
- (NSString *)openUDID  
{  
    NSString *identifierForVendor = [[UIDevice currentDevice].identifierForVendor UUIDString];  
    return identifierForVendor;  
}  

#pragma mark 保存UUID到钥匙串  
- (void)saveUDID:(NSString *)udid  
{  
    NSMutableDictionary *udidKVPairs = [NSMutableDictionary dictionary];  
    [udidKVPairs setObject:udid forKey:KEY_UDID];  
    [[APPIdentificationManage sharedAPPIdentificationManage] save:KEY_IN_KEYCHAIN data:udidKVPairs];  
}  

#pragma mark 读取UUID  
/** 
 *先从内存中获取uuid,如果没有再从钥匙串中获取,如果还没有就生成一个新的uuid,并保存到钥匙串中供以后使用 
 **/  
- (id)readUDID  
{  
    if (_uuid == nil || _uuid.length == 0) {  
        NSMutableDictionary *udidKVPairs = (NSMutableDictionary *)[[APPIdentificationManage sharedAPPIdentificationManage] load:KEY_IN_KEYCHAIN];  
        NSString *uuid = [udidKVPairs objectForKey:KEY_UDID];  
        if (uuid == nil || uuid.length == 0) {  
            uuid = [self openUDID];  
            [self saveUDID:uuid];  
        }  
        _uuid = uuid;  
    }  
    return _uuid;  
}  

#pragma mark 删除UUID  
- (void)deleteUUID  
{  
    [APPIdentificationManage delete:KEY_IN_KEYCHAIN];  
}  

#pragma mark 查询钥匙串  
- (NSMutableDictionary *)getKeychainQuery:(NSString *)service {  
    return [NSMutableDictionary dictionaryWithObjectsAndKeys:  
            (__bridge_transfer id)kSecClassGenericPassword,(__bridge_transfer id)kSecClass,  
            service, (__bridge_transfer id)kSecAttrService,  
            service, (__bridge_transfer id)kSecAttrAccount,  
            (__bridge_transfer id)kSecAttrAccessibleAfterFirstUnlock,(__bridge_transfer id)kSecAttrAccessible,  
            nil nil];  
}  

#pragma mark 将数据保存到钥匙串  
- (void)save:(NSString *)service data:(id)data {  
    NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];  
    SecItemDelete((__bridge_retained CFDictionaryRef)keychainQuery);  
    [keychainQuery setObject:[NSKeyedArchiver archivedDataWithRootObject:data] forKey:(__bridge_transfer id)kSecValueData];  
    SecItemAdd((__bridge_retained CFDictionaryRef)keychainQuery, NULL);  
}  

#pragma mark 加载钥匙串中数据  
- (id)load:(NSString *)service {  
    id ret = nil;  
    NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];  

    [keychainQuery setObject:(id)kCFBooleanTrue forKey:(__bridge_transfer id)kSecReturnData];  
    [keychainQuery setObject:(__bridge_transfer id)kSecMatchLimitOne forKey:(__bridge_transfer id)kSecMatchLimit];  
    CFDataRef keyData = NULL;  
    if (SecItemCopyMatching((__bridge_retained CFDictionaryRef)keychainQuery, (CFTypeRef *)&keyData) == noErr) {  
        @try {  
            ret = [NSKeyedUnarchiver unarchiveObjectWithData:(__bridge_transfer NSData *)keyData];  
        } @catch (NSException *e) {  
            NSLog(@"Unarchive of %@ failed: %@", service, e);  
        } @finally {  
        }  
    }  
    return ret;  
}  

#pragma mark 删除钥匙串中数据  
- (void)delete:(NSString *)service {  
    NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];  
    SecItemDelete((__bridge_retained CFDictionaryRef)keychainQuery);  
}  
@end  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值