UDID

全名:Unique Device Identifie(设备唯一标识符)

说明:UDID,即设备唯一标识符,这是除序列号之外每台iOS设备的独一无二的号码。UDID只是和设备相关的,是用来区分每一个唯一的iOS设备(包括iPhone、iPad等),是由40个字符的字母和数字组成的。

作用:可以关联其它各种数据到相关设备上。比如:程序发布前的通过测试版本进行测试等都需要UDID。

获取方法: UDID可以直接通过ITunes查看,手机连接上电脑之后点击序列号就会变成UDID,如下图。也可以通过Xcode查看:点击Window->Devices and Simulators->identifier就能看到,如下图。

代码获取方法:

在iOS5之后,苹果就禁止了通过代码获取UDID。转而用[UIDevice currentDevice].identifierForVendor.UUIDString替代。但是这个不是真正的UDID.关闭的原因是因为隐私问题。之后苹果禁止上架试图获取UDID的应用。

UUID

全名:Universally Unique Identifier(通用唯一标识符)

说明:UUID是一个通过小横线连接起来的32位的十六进制序列。如0DEF9507-EB5A-471A-8BC7-638A0B0A327D。但是UUID并不像UDID一样是惟一的,它只是在某一时空是唯一的,当每次写在应用之后获取到的UUID都是不一样的。比如通过一个for循环打印一下UUID能就能看出不一样:

for (int i = 0; i < 5; i ++) {

NSLog(@"uuid %zd = %@", i,[NSUUID UUID].UUIDString);

}

那是不是这样就不能唯一标识了呢?并不是,开发者可以将这个UUID保存在keychain里面,以此作为唯一标识符。接下来会讲到。

代码获取UUID:

NSString * uuid = [NSUUID UUID].UUIDString;

用keychain保存UUID

keychain介绍

苹果在OS X和IOS系统都有提供的一种安全存储敏感信息的工具,即keychain。所谓铭感信息,即用户ID、password、certificate等。keychain里面存储的数据是item。这些item是以key-value的形式存储的,可以理解为Dictonary。利用keychain存储这些信息可以提高用户体验,免除用户重复输入用户名和密码等繁琐的操作。同时,苹果的这套keychain Service安全机制能够保障存储的信息不会被窃取,所以可以用来存储UUID等。

为什么要用keychain?

keychain的数据并非是存放在应用程序的沙盒中,所以即使当用户删除app,存储的资料依然在keychain中。用户再一次安装该应用程序的时候又可以从keychain中获取数据。

keychain的数据有经过加密,更安全。

keychain提供了一个公共区"keychain access group",可以通过这个group实现应用程序之间的数据共享。

keychain中的item

keychain中是存放的item。并且可以存放任意数量的item。keychain会对需要加密的item进行加密保护,比如:密码。而对于像证书就就不会加密。

在苹果提供的API中可以看到有五种类型的item:

kSecClassInternetPassword //Specifies Internet password items.

kSecClassGenericPassword //Specifies generic password items.

kSecClassCertificate //Specifies certificate items.

kSecClassKey //Specifies key items.

kSecClassIdentity //Specifies identity items.

苹果提供了四种操作item的方法,即增、删、改、查操作:

// 1. 查询已存在的item/items

SecItemCopyMatching(CFDictionaryRef query, CFTypeRef * __nullable CF_RETURNS_RETAINED result)

// 2. 添加 item/items到keychain

SecItemAdd(CFDictionaryRef attributes, CFTypeRef * __nullable CF_RETURNS_RETAINED result)

// 3. 更新已存在的item/items

SecItemUpdate(CFDictionaryRef query, CFDictionaryRef attributesToUpdate)

// 4. 删除已存在的 item/items

SecItemDelete(CFDictionaryRef query)

代码环节

可以写一个KeychainWrapper工具类来实现keychain的操作。核心代码如下

// 根据特定的Service创建一个用于操作KeyChain的Dictionary

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

{

// 添加的字典不懂?

return [NSMutableDictionary dictionaryWithObjectsAndKeys:

(__bridge id)(kSecClassGenericPassword), kSecClass,

service, kSecAttrService,

service, kSecAttrAccount,

kSecAttrAccessibleAfterFirstUnlock, kSecAttrAccessible,

nil];

}

// 保存数据到keychain中

+ (BOOL)saveDate:(id)date withService:(NSString *)service

{

// 1. 创建dictonary

NSMutableDictionary * keychainQuery = [self getKeychainQuery:service];

// 2. 先删除

SecItemDelete((CFDictionaryRef)keychainQuery);

// 3. 添加到date到query中

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

// 4. 存储到到keychain中

OSStatus status = SecItemAdd((CFDictionaryRef)keychainQuery, NULL);

return status == noErr ? YES : NO;

}

// 从keychain中查找数据

+ (id)searchDateWithService:(NSString *)service

{

id retsult = nil;

NSMutableDictionary * keychainQuery = [self getKeychainQuery:service];

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

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

CFTypeRef resultDate = NULL;

if (SecItemCopyMatching((CFDictionaryRef)keychainQuery, &resultDate)== noErr) {

@try{

retsult = [NSKeyedUnarchiver unarchiveObjectWithData:(__bridge NSData *)resultDate];

}

@catch(NSException *e){

NSLog(@"查找数据不存在");

}

@finally{

}

}

if (resultDate) {

CFRelease(resultDate);

}

return retsult;

}

// 更新keychain中的数据

+ (BOOL)updateDate:(id)date withService:(NSString *)service

{

NSMutableDictionary * searchDictonary = [self getKeychainQuery:service];

if (!searchDictonary) {return NO;}

NSMutableDictionary * updateDictonary = [NSMutableDictionary dictionary];

[updateDictonary setObject:[NSKeyedArchiver archivedDataWithRootObject:date] forKey:(id)kSecValueData];

OSStatus status = SecItemUpdate((CFDictionaryRef)searchDictonary, (CFDictionaryRef)updateDictonary);

return status == noErr ? YES : NO;

}

// 删除keychain中的数据

+ (BOOL)deleteDateiWithService:(NSString *)service

{

NSMutableDictionary * keychainQuery = [self getKeychainQuery:service];

OSStatus status = SecItemDelete((CFDictionaryRef)keychainQuery);

return status == noErr ? YES : NO;

}

使用keychain保存UUID

有了上面的方法,接下来就操作就很简单了:

/**

先从keychain里面加载uuid 如果没有 就获取uuid并加载到keychain中

*/

+ (NSString *)getUUIDfromKeychain

{

NSString * uuid = NULL;

uuid = [KeychainWrapper searchDateWithService:DEMO_UUID];

if (uuid) {

return uuid;

}else{

uuid = [self getRandomUUID];

if([KeychainWrapper saveDate:uuid withService:DEMO_UUID]){

return uuid;

}else{

return NULL;

}

}

}

+ (NSString *)getRandomUUID

{

return [NSUUID UUID].UUIDString;

}

打印出来发现获取的uuid是一样的,说明keychain保存成功了:

IDFA

全名:Identifier for Advertising(广告标示符)

python获取机器唯一标识_开发中常用工具 - 获取设备的唯一标识、UDID、UUID、keychain保存UUID、判断网络...相关推荐

  1. python调用按键精灵插件_开发中IDE的选择?如何在VsCode上配置CC++,Java,Python环境...

    前言 工欲善其事必先利其器,这也是老生常谈的事情了.在做日常开发中,让我感受到一个顺手的开发工具的重要性.截至目前对于不同语言自己也使用过很多开发工具,有一些简单的编辑器例如:notepad++.Ed ...

  2. j2EE开发中常用工具软件

    一.文本编辑器 1.notepad++ 2.editplus 3.Uedit32 4.gVim/Vim 二.java class反编译器 1.XJad 2.jd-gui 三.远程连接工具 1.Xman ...

  3. python web开发第三方库_Python Web开发中常用的第三方库

    Python Web开发中常用的第三方库 TL;DR 经常有朋友问,如果用Python来做Web开发,该选用什么框架?用 Pyramid 开发Web该选用怎样的组合等问题?在这里我将介绍一些Pytho ...

  4. 手机直播系统开发中关于iOS获取图形验证码功能

    在手机直播系统开发中关于iOS获取图形验证码功能介绍,首先进入注册页面后请求图形验证码接口获取图形验证码的数字组合,然后加载到相应的页面上,在图形验证码页面我们定义了几个属性,字符串的数量.显示的线条 ...

  5. android motionevent 坐标,Android开发中MotionEvent坐标获取方法分析

    本文实例讲述了Android开发中MotionEvent坐标获取方法.分享给大家供大家参考,具体如下: Android MotionEvent中getX()与getRawX()都是获取屏幕坐标(横), ...

  6. iOS开发中常用的方法

    iOS开发中常用的方法 系统弹窗: 过期方法: UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:@"确认报价" ...

  7. java开发常用jar包_Java开发中常用jar包整理及使用

    本文整理了我自己在Java开发中常用的jar包以及常用的API记录. 一.common-lang3 简介:一个现在最为常用的jar包,封装了许多常用的工具包 依赖: org.apache.common ...

  8. php页面开发,PHP网站开发中常用的8个小技巧

    这篇文章主要介绍了PHP网站开发中常用的8个小技巧,本文讲解了命名.使用.PHP判断Form表单是否提交.PHP 获取字符串长度.PHP超全局对象等内容,需要的朋友可以参考下 PHP是一种用于创建动态 ...

  9. Java开发中常用的设计模式-单例模式

    单例(Singleton)模式的定义:指一个类只有一个实例,且该类能自行创建这个实例的一种模式. Java开发中常用的设计模式-单例模式 单例模式有3个特点: 单例类只有一个实例对象: 该单例对象必须 ...

最新文章

  1. 连发10篇SCI!徐州二本学霸全奖直博香港城大引热议
  2. 如何在Linux下统计高速网络中的流量
  3. 天翼云从业认证(4.8)高性能计算解决方案
  4. git安装错误:can not read system config
  5. mybatis mysql schema_学习Mybatis与mysql数据库的示例笔记
  6. kepware omronFINS
  7. 动手学深度学习(三十四)——序列模型
  8. 计算机房设计规范2008,电子计算机房设计规范.doc
  9. 麦肯锡三部曲_《麦肯锡精英高效阅读法》| 认知的四种境界,来看看自己在哪一层...
  10. Python:OpenCV4人脸关键点检测以及表情检测
  11. 三极管的基础知识(下)①
  12. 硬盘数据恢复方法有哪些?希望这些方法能帮助你
  13. 拓嘉启远:怎样做拼多多推广见效是比较快的
  14. fagor后处理格式_输出格式
  15. android app调用第三方地图路线规划导航(百度,高德,腾讯)
  16. 关于微信公众平台本地测试ip如何加入IP白名单
  17. was服务器里面jar包_如何在was中解决jar包冲突
  18. Firefox浏览器基本使用
  19. 修复自定义标题word题注错误:错误,文档中没有指定样式的文字以及编号无法随章节变化问题
  20. 互联网+下PDA移动智能手持POS超市收银开单软件

热门文章

  1. Android 常见异常及解决办法
  2. solr单机版的搭建
  3. Windows Phone 7编程学习点滴一——页面切换、返回键重载和工具栏
  4. 异步编程之Promise(2):探究原理
  5. Android OpenGL使用GLSurfaceView预览视频
  6. FastDFS安装与使用
  7. PHP安装扩展mcrypt以及相关依赖项 【PHP安装PECL扩展的方法】
  8. HTTP头信息中的参数Etag
  9. 用C#实现基于TCP协议的网络通讯
  10. ASP.NET2.0 GridView小技巧汇粹