问题1:[[UIDevice currentDevice] identifierForVendor].UUIDString什么情况下值会变化?

[[UIDevice currentDevice] identifierForVendor].UUIDString 是一个用于标识设备的唯一标识符(UUID),针对同一应用程序供应商(即同一开发者的应用程序集合),在设备上不变。然而,有一些情况会导致这个标识符发生变化:

情况导致 identifierForVendor 变化:

  1. 应用卸载和重装:当设备上来自同一供应商的所有应用程序都被卸载,再重新安装任意一个应用程序时,会生成新的 identifierForVendor。这意味着,如果用户完全清除你的应用并重新安装,它会获得一个新值。

  2. 设备恢复出厂设置:如果设备被恢复出厂设置,也会生成新的 identifierForVendor

除此之外,identifierForVendor 不会因为设备上的通常操作(如重启设备、软件更新等)而改变。

存储到 Keychain 的优势

Keychain 是一个安全存储敏感信息的系统级服务,适用于存储比如密码、证书和加密密钥等重要数据。把 identifierForVendor 存储到 Keychain 有一些优势:

  1. 持久性:即使用户删除了应用,Keychain 中存储的数据不会被删除。当用户重新安装应用时,可以从 Keychain 中恢复数据。
  2. 安全性:Keychain 提供了高安全性的存储方式,对敏感数据的保护比普通的文件存储要好得多。
  3. 跨应用共享:在适当的配置下,同一供应商的应用程序可以共享 Keychain 中的数据。

下面是将 identifierForVendor 存储到 Keychain 的示例代码:

#import <Security/Security.h>

- (void)storeIdentifierForVendorInKeychain {
NSString *uuid = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
NSString *key = @"com.yourcompany.yourapp.identifierForVendor"; // 删除之前存储的 UUID
[self deleteUUIDFromKeychain:key]; NSData *uuidData = [uuid dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *query = @{
(id)kSecClass: (id)kSecClassGenericPassword,
(id)kSecAttrAccount: key,
(id)kSecValueData: uuidData,
}; OSStatus status = SecItemAdd((CFDictionaryRef)query, NULL);
if (status == errSecSuccess) {
NSLog(@"UUID stored successfully.");
} else {
NSLog(@"Error storing UUID: %d", (int)status);
}
} - (NSString *)retrieveUUIDFromKeychain {
NSString *key = @"com.yourcompany.yourapp.identifierForVendor"; NSDictionary *query = @{
(id)kSecClass: (id)kSecClassGenericPassword,
(id)kSecAttrAccount: key,
(id)kSecReturnData: (id)kCFBooleanTrue,
}; CFDataRef dataRef = NULL;
OSStatus status = SecItemCopyMatching((CFDictionaryRef)query, (CFTypeRef *)&dataRef); if (status == errSecSuccess) {
NSData *resultData = (__bridge NSData *)dataRef;
NSString *uuid = [[NSString alloc] initWithData:resultData encoding:NSUTF8StringEncoding];
CFRelease(dataRef);
return uuid;
} else {
NSLog(@"Error retrieving UUID: %d", (int)status);
return nil;
}
} - (void)deleteUUIDFromKeychain:(NSString *)key {
NSDictionary *query = @{
(id)kSecClass: (id)kSecClassGenericPassword,
(id)kSecAttrAccount: key,
}; OSStatus status = SecItemDelete((CFDictionaryRef)query);
if (status == errSecSuccess) {
NSLog(@"UUID deleted successfully.");
} else {
NSLog(@"Error deleting UUID: %d", (int)status);
}
}

步骤:

  1. 存储 UUID:使用 storeIdentifierForVendorInKeychain 方法将 identifierForVendor 存储到 Keychain 中。
  2. 检索 UUID:使用 retrieveUUIDFromKeychain 方法从 Keychain 中检索存储的 UUID。
  3. 删除 UUID:使用 deleteUUIDFromKeychain 方法删除存储的 UUID。

通过这些步骤和方法,你可以确保即使应用被删除和重新安装,也可以从 Keychain 中恢复先前的 identifierForVendor,保持UUID的一致性。

问题2:存储到 Keychain,什么情况下值会变化 ?

存储在 Keychain 中的数据通常在一些特定情况下会发生变化。以下是其中一些主要情形:

1. 恢复出厂设置

恢复出厂设置会清除设备上的所有数据,包括应用数据、用户文件、系统设置和 Keychain 数据。在这种情况下,Keychain 中存储的任何值(例如标识符、密码等)都会被删除并且无法恢复。

2. 刷机

刷机通常指的是重新安装设备的固件或操作系统。刷机过程也会清除设备上的所有数据,包括 Keychain 中的数据。因此,存储在 Keychain 中的值会被删除。

3. 应用被卸载

不同于普通的文件存储,Keychain 中的数据在应用被卸载时不会被删除。当应用重新安装时,可以继续访问先前存储的 Keychain 数据。然而,如果用户选择了“删除应用的数据”或使用特定第三方工具清理 Keychain 数据,相关的存储值可能会被删除。

4. 设备迁移

在某些情况下,通过 iCloud 备份或设备迁移将 Keychain 数据同步到新设备上。如果用户选择没有迁移 Keychain 数据(例如,设备迁移时选择了不备份 Keychain),那么新设备中的值会发生变化或丢失。

5. 越狱设备

越狱会增加 Keychain 数据被第三方工具访问、修改或删除的风险。尽管越狱本身不会直接改变 Keychain 中的值,但越狱后的应用和操作可能影响其数据完整性,可能导致 Keychain 数据被篡改或清除。

6. 应用自身操作

如果应用在某些条件下(如用户登出、换新账户、重装等)主动删除或更新 Keychain 中的数据,也会导致相关值发生变化。例如:

- (void)deleteIdentifierInKeychain {
NSString *key = @"com.yourcompany.yourapp.identifierForVendor";
NSDictionary *query = @{
(id)kSecClass: (id)kSecClassGenericPassword,
(id)kSecAttrAccount: key,
}; OSStatus status = SecItemDelete((CFDictionaryRef)query);
if (status == errSecSuccess) {
NSLog(@"UUID deleted successfully.");
} else {
NSLog(@"Error deleting UUID: %d", (int)status);
}
}

7. 用户主动清除 Keychain

用户可以通过某些工具或设置,主动选择清除特定的 Keychain 数据,这样会导致存储值的删除或变化。

常见问题:

  • 卸载和重新安装应用

    • 不恢复出厂设置:重装应用通常不会影响 Keychain 数据。
    • 恢复出厂设置或重置所有设置:Keychain 数据会被删除。
  • 设备切换

    • 如果用户在设备切换过程中未备份或恢复 Keychain 数据,新的 Keychain 数据将重新生成。

简而言之,尽管 Keychain 存储提供了一种相对持久的存储机制,在以下情况下存储值可能会发生变化或被清除:

  1. 恢复出厂设置或刷机。
  2. 设备迁移而未同步 Keychain 数据。
  3. 越狱引起的数据篡改或清除。
  4. 应用自身操作或用户主动清除 Keychain 数据。

iOS开发基础149-由UUIDString引发的思考的更多相关文章

  1. IOS开发基础知识碎片-导航

    1:IOS开发基础知识--碎片1 a:NSString与NSInteger的互换 b:Objective-c中集合里面不能存放基础类型,比如int string float等,只能把它们转化成对象才可 ...

  2. iOS开发——总结篇&IOS开发基础知识

    IOS开发基础知识 1:Objective-C语法之动态类型(isKindOfClass, isMemberOfClass,id) 对象在运行时获取其类型的能力称为内省.内省可以有多种方法实现. 判断 ...

  3. IOS开发基础环境搭建

    一.目的 本文的目的是windows下IOS开发基础环境搭建做了对应的介绍,大家可根据文档步骤进行mac环境部署: 二.安装虚拟机 下载虚拟机安装文件绿色版,点击如下文件安装 获取安装包:       ...

  4. iOS开发基础-九宫格坐标(6)

    继续对iOS开发基础-九宫格坐标(5)中的代码进行优化. 优化思路:把字典转模型部分的数据处理操作也拿到模型类中去实现,即将 ViewController 类实现中 apps 方法搬到 WJQAppI ...

  5. iOS开发基础-九宫格坐标(5)

    继续在iOS开发基础-九宫格坐标(4)的基础上进行优化. 一.改进思路 1)iOS开发基础-九宫格坐标(4)中 viewDidLoad 方法中的第21.22行对控件属性的设置能否拿到视图类 WJQAp ...

  6. iOS开发基础-九宫格坐标(4)

    对iOS开发基础-九宫格坐标(3)的代码进行进一步优化. 新建一个 UIView 的子类,并命名为 WJQAppView ,将 appxib.xib 中的 UIView 对象与新建的视图类进行关联. ...

  7. iOS开发基础-九宫格坐标(3)之Xib

    延续iOS开发基础-九宫格坐标(2)的内容,对其进行部分修改. 本部分采用 Xib 文件来创建用于显示图片的 UIView 对象. 一.简单介绍  Xib 和 storyboard 的比较: 1) X ...

  8. iOS开发基础-九宫格坐标(2)之模型

    在iOS开发基础-九宫格(1)中,属性变量 apps 是从plist文件中加载数据的,在 viewDidLoad 方法中的第20行.26行中,直接通过字典的键名来获取相应的信息,使得 ViewCont ...

  9. iOS开发基础-图片切换(4)之懒加载

    延续:iOS开发基础-图片切换(3),对(3)里面的代码用懒加载进行改善. 一.懒加载基本内容 懒加载(延迟加载):即在需要的时候才加载,修改属性的 getter 方法. 注意:懒加载时一定要先判断该 ...

  10. iOS开发基础-图片切换(3)之属性列表

    延续:iOS开发基础-图片切换(2),对(2)里面的代码用属性列表plist进行改善. 新建 Property List 命名为 Data 获得一个后缀为 .plist 的文件. 按如图修改刚创建的文 ...

随机推荐

  1. CentOS7学习笔记(三) 用户和用户组管理

    用户管理 Linux中root用户是权限最大的用户,一般情况下只有服务器管理员拥有root用户的使用权,而我们会使用其他用户来连接Linux 创建用户的命令 创建用户的命令是useradd name, ...

  2. 快速上手Python编程

    前言 .center { width: auto; display: table; margin-left: auto; margin-right: auto } 类型 原理 优点 缺点 编译型语言 ...

  3. Rust性能分析之测试及火焰图,附(lru,lfu,arc)测试

    性能测试,在编写代码后,单元测试及性能测试是重要的验收点,好的性能测试可以让我们提前发现程序中存在的问题. 测试用例 在Rust中,测试通常有两部分,一部分是文档测试,一部分是模块测试. 通常我们在函 ...

  4. 【UnityTips】如何自定义脚本模版

    [UnityTips]如何自定义脚本模版 通常我们创建新脚本时大家看到的是这个样子: using System.Collections; using System.Collections.Generi ...

  5. EthernetIP IO从站设备数据 转 Modbus RTU TCP项目案例

    1         案例说明 1.   设置网关采集EthernetIP IO设备数据 2.   把采集的数据转成Modbus协议转发给其他系统. 2        VFBOX网关工作原理 VFBOX ...

  6. 【FAQ】HarmonyOS SDK 闭源开放能力 —Map Kit(2)

    1.问题描述: 能否设置点击地图,地图标记上的文字不消失? 解决方案: 你好,这个功能设计本身就是点击屏幕marker的信息窗消失:如果用户只是想信息窗中的文字一直展示,可以不用信息窗实现 ,建议可以 ...

  7. 从PDF到OFD,国产化浪潮下多种文档格式导出的完美解决方案

    前言 近年来,中国在信息技术领域持续追求自主创新和供应链安全,伴随信创上升为国家战略,一些行业也开始明确要求文件导出的格式必须为 OFD 格式.OFD 格式目前在政府.金融.税务.教育.医疗等需要文件 ...

  8. 量子算法抛转(以及Oracle函数初步)

    接下来要接触量子算法了,我们会看到怎么利用量子并行机制和干涉原理.干涉在算法对结果进行测量求值时举足轻重. Deutsch-Jozsa 算法 DJ算法是量子算法的入门算法,就像编程界的"He ...

  9. 记一次aspnetcore发布部署流程初次使用k8s

    主题: aspnetcorewebapi项目,提交到gitlab,通过jenkins(gitlab的ci/cd)编译.发布.推送到k8s. 关于gitlab.jenkins.k8s安装,都是使用doc ...

  10. 全网最适合入门的面向对象编程教程:10 类和对象的 Python 实现-类的继承和里氏替换原则,Python 模拟主机和传感器自定义类

    全网最适合入门的面向对象编程教程:10 类和对象的 Python 实现-类的继承和里氏替换原则,Python 模拟主机和传感器自定义类 摘要: 本文主要介绍了类的继承的基本概念和里氏替换原则,以模拟传 ...