美文网首页
iOS 唯一识别码 IDFV+keychain

iOS 唯一识别码 IDFV+keychain

作者: frankyfz | 来源:发表于2017-09-07 09:50 被阅读127次

    这段时间用到了iPhone的唯一标识,找到了不少方法,认为较好用的且现在可行的有两种。一是IDFV另一个是IDFA,前者identifierForVendor是apple给供应商唯一的一个值,也就是说同一个公司发行的的app在相同的设备上运行的时候会有这个相同的标识符。然而,如果用户删除了这个供应商的所有app然后再重新安装的话,这个标识符就会不一致。后者advertisingIdentifier则是给在这个设备上所有软件供应商相同的一个值,一般在广告的时候使用。这个值虽然不会因为重装app改变,但是在某些情况下还是会改变。如果用户完全重置系统((设置程序 -> 通用 -> 还原 -> 还原位置与隐私) ,这个广告标示符会重新生成。另外如果用户明确的还原广告(设置程序-> 通用 -> 关于本机 -> 广告 -> 还原广告标示符) ,那么广告标示符也会重新生成。关于广告标示符的还原,还有一点需要注意:如果程序在后台运行,此时用户“还原广告标示符”,然后再回到程序中,此时获取广告标示符并不会立即获得还原后的标示符。必须要终止程序,然后再重新启动程序,才能获得还原后的广告标示符。

    获取方法如下:

    NSString *identifierForVendor = [[UIDevice currentDevice].identifierForVendor UUIDString];

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

    相比卸载重装,IDFA还是较稳定的,但是用IDFA在送审的时候,要表明用了广告标识符,并且要导入依赖库,为了不引起必要麻烦,本人采用了IDFV+keychain的方法。keychain是iPhone的一个机制。将信息保存在系统,这些信息不随app的卸载重装而消失。

    先简单介绍下IDFA的导入方法:

    ---------------------------------------------------------------------------

    1、添加框架       本人刚开始导入的是security.framework  测试也可以使用

    AdSupport.framework

    2、添加头文件

    #import

    3、使用语句

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

    -----------------------------------------------------------------------------

    重点是IDFV+keychain这种方法 封装在一个工具类中 非常好用   ok上代码

    Tools.h中

    +++++++++++++++++++++

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

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

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

    + (NSString *)getIDFV;

    ++++++++++++++++++++++

    Tools.m中

    =================================

    + (NSString *)getIDFV

    {

    //定义存入keychain中的账号 也就是一个标识 表示是某个app存储的内容   bundle id就好

    NSString * const KEY_USERNAME_PASSWORD = @"com.danson.zzzz.usernamepassword";

    NSString * const KEY_PASSWORD = @"com.danson.zzzz.password";

    //测试用 清除keychain中的内容

    //[Tools delete:KEY_USERNAME_PASSWORD];

    //读取账号中保存的内容

    NSMutableDictionary *readUserPwd = (NSMutableDictionary *)[Tools load:KEY_USERNAME_PASSWORD];

    //NSLog(@"keychain------><>%@",readUserPwd);

    if (!readUserPwd) {

    //如果为空 说明是第一次安装 做存储操作

    NSString *identifierStr = [[[UIDevice currentDevice] identifierForVendor] UUIDString];

    //NSLog(@"identifierStr-----><>%@",identifierStr);

    NSMutableDictionary *usernamepasswordKVPairs = [NSMutableDictionary dictionaryWithObject:identifierStr forKey:KEY_PASSWORD];

    [Tools save:KEY_USERNAME_PASSWORD data:usernamepasswordKVPairs];

    return identifierStr;

    }else{

    return [readUserPwd objectForKey:KEY_PASSWORD];

    }

    }

    //储存

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

    //Get search dictionary

    NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];

    //Delete old item before add new item

    SecItemDelete((__bridge CFDictionaryRef)keychainQuery);

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

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

    //Add item to keychain with the search dictionary

    SecItemAdd((__bridge CFDictionaryRef)keychainQuery, NULL);

    }

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

    return [NSMutableDictionary dictionaryWithObjectsAndKeys:

    (__bridge id)kSecClassGenericPassword,(__bridge id)kSecClass,

    service, (__bridge id)kSecAttrService,

    service, (__bridge id)kSecAttrAccount,

    (__bridge id)kSecAttrAccessibleAfterFirstUnlock,(__bridge id)kSecAttrAccessible,

    nil];

    }

    //取出

    + (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:(__bridge id)kCFBooleanTrue forKey:(__bridge id)kSecReturnData];

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

    CFDataRef keyData = NULL;

    if (SecItemCopyMatching((__bridge 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)delete:(NSString *)service {

    NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];

    SecItemDelete((__bridge CFDictionaryRef)keychainQuery);

    }

    ================================

    调用的时候

    直接 [Tools getIDFV] 就可以了   暂时还不知道 系统会不会把卸载重装前生成的IDFA给别的开发商 如果会重新分配 就可能会产生重复的 待考证

    ok 到这里就结束了  希望可以让阅读者节省点时间

    参考资料  http://www.cnblogs.com/qingjoin/p/3549325.html

    相关文章

      网友评论

          本文标题:iOS 唯一识别码 IDFV+keychain

          本文链接:https://www.haomeiwen.com/subject/tnbbjxtx.html