美文网首页iOS『技术栈』iOSiOS小超人
iOS 获取设备唯一标示符的方法

iOS 获取设备唯一标示符的方法

作者: LannisZheng | 来源:发表于2015-10-30 00:18 被阅读33475次

    在开发中会遇到应用需要记录设备标示,即使应用卸载后再安装也可重新识别的情况,在这写一种实现方式——读取设备的UUID(Universally Unique Identifier)并通过KeyChain记录。

    首先iOS中获取设备唯一标示符的方法一直随版本的更新而变化。iOS 2.0版本以后UIDevice提供一个获取设备唯一标识符的方法uniqueIdentifier,通过该方法我们可以获取设备的序列号,这个也是目前为止唯一可以确认唯一的标示符。好景不长,因为该唯一标识符与手机一一对应,苹果觉得可能会泄露用户隐私,所以在 iOS 5.0之后该方法就被废弃掉了;iOS 6.0系统新增了两个用于替换uniqueIdentifier的接口,分别是:identifierForVendor,advertisingIdentifier,但这两个接口会在应用重新安装时改变数值,并不是唯一的标示符,所以开发者改为使用WiFi的mac地址来取代;iOS 7中苹果又封杀mac地址,所以开发者再次改变思路使用KeyChain来保存获取到的UDID,这样以后即使APP删了再装回来,也可以从KeyChain中读取回来。

    首先保存设备的UUID,可以使用类方法+ (id)UUID 是一个类方法,调用该方法可以获得一个UUID。通过下面的代码可以获得一个UUID字符串:

     NSString *uuid = [[NSUUID UUID] UUIDString];
    

    也可以保存在iOS 6中新增的Vindor标示符 (IDFV-identifierForVendor),获取这个IDFV的新方法被添加在已有的UIDevice类中。跟advertisingIdentifier一样,该方法返回的是一个NSUUID对象。

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

    如果用户卸载了同一个vendor对应的所有程序,然后在重新安装同一个vendor提供的程序,此时identifierForVendor会被重置,所以这里要用到KeyChain来保存。
    KeyChain(钥匙串)是使用苹果设备经常使用的,通常要调试的话,都得安装证书之类的,这些证书就是保存在KeyChain中,还有我们平时浏览网页记录的账号密码也都是记录在KeyChain中。iOS中的KeyChain相比OS X比较简单,整个系统只有一个KeyChain,每个程序都可以往KeyChain中记录数据,而且只能读取到自己程序记录在KeyChain中的数据。iOS中Security.framework框架提供了四个主要的方法来操作KeyChain:

    • SecItemCopyMatching(CFDictionaryRef query, CFTypeRef *result);//查询OSStatus
    • SecItemAdd(CFDictionaryRef attributes, CFTypeRef *result); //添加OSStatus
    • SecItemUpdate(CFDictionaryRef query, CFDictionaryRef attributesToUpdate);//更新KeyChain中的ItemOSStatus
    • SecItemDelete(CFDictionaryRef query)//删除KeyChain中的ItemOSStatus

    这四个方法参数比较复杂,一旦传错就会导致操作KeyChain失败,文档中介绍的比较详细,大家可以查查官方文档。而苹果提供的KeyChain使用起来略麻烦,所以这里推荐一个第三方库SAMKeyChains.SAMKeyChains对苹果安全框架API进行了简单封装,支持对存储在钥匙串中密码、账户进行访问,包括读取、删除和设置。SAMKeyChains使用简单,通过实例代码便可掌握。

    //保存一个UUID字符串到钥匙串:
    CFUUIDRef uuid = CFUUIDCreate(NULL);
    assert(uuid != NULL);
    CFStringRef uuidStr = CFUUIDCreateString(NULL, uuid);
     [SAMKeychain setPassword: [NSString stringWithFormat:@"%@", uuidStr]
     forService:@"com.yourapp.yourcompany"account:@"user"];
     
    //从钥匙串读取UUID:
    NSString *retrieveuuid = [SAMKeychain passwordForService:@"com.yourapp.yourcompany"account:@"user"];
     
    **注意: setPassword和passwordForSevice方法中的**services 和 accounts 参数应该是一致的。
    

    更多详细用法说明可以看SAMKeyChains Documentation

    基本的实现思路便是这样,下面是具体的一种具体实现代码,仅供参考。

    + (NSString *)getDeviceId
    {
        NSString * currentDeviceUUIDStr = [SAMKeychain passwordForService:@" "account:@"uuid"];
        if (currentDeviceUUIDStr == nil || [currentDeviceUUIDStr isEqualToString:@""])
        {
            NSUUID * currentDeviceUUID  = [UIDevice currentDevice].identifierForVendor;
            currentDeviceUUIDStr = currentDeviceUUID.UUIDString;
            currentDeviceUUIDStr = [currentDeviceUUIDStr stringByReplacingOccurrencesOfString:@"-" withString:@""];
            currentDeviceUUIDStr = [currentDeviceUUIDStr lowercaseString];
            [SAMKeychain setPassword: currentDeviceUUIDStr forService:@" "account:@"uuid"];
        }
        return currentDeviceUUIDStr;
    }
    

    相关文章

      网友评论

      • 丫丫_dyl:想问下,如果手机升级系统的话,唯一标示存在钥匙串中有影响吗?
        丫丫_dyl:@LannisZheng 好的,谢谢
        LannisZheng:@丫丫_dyl 不影响,钥匙串中的数据不会变化
      • YimG:为什么我获取的UDID跟我iCloud里面获取的UDID不一样?
      • Real_young:这个框架是不是要设置什么ARC的
      • 七月不下雨:请问一下 com.yourapp.yourcompany 这个 是随便写的 还是 什么,谢谢
      • 晴天有雨丶:SSKeychain 这个类需要百度搜一下就好,给和我一样蠢的人查看!!!!!!!!
      • maretell:现在 用什么方法获取唯一标示? 能不影响上架 急!!!
        LannisZheng:@maretell 这样就可以
      • 56d35fdf1a2a:是不是现在就不能使用UDID来作为标识符了
      • 冲天小飞机:但问题是keychain是一个会被iCloud同步的东西,那么假如这个用户是有两台设备的话,iCloud一同步,那么获取这两台设备的udid就会变成了同一个。
        广锅锅:@Crazy周 我也在想这个问题,不过,如果是同一个人的,并且两台都装了这个软件,发送消息什么的,两个都收到也未尝不好。
      • Eddie_Zys:如果系统升级,这种方式还好用嘛?重新刷系统肯定是不行的。
        小赢一场:@Sea_god 升级系统是不会清除keyChain中数据的,应该好用
      • 杏仁丶:赞一个,以后肯定会用的到的!

      本文标题:iOS 获取设备唯一标示符的方法

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