将唯一 ID 实现为 UUID 并将其保存在 Keychain 中

2024-04-07

我的应用程序中需要唯一 ID,我知道,我们不能再使用 UDID,因此根据我的研究,使用 UUID 作为设备唯一 ID 并将其保存在钥匙串中将确保即使用户重新安装我的应用程序,唯一 ID 仍保持不变。

我从 stackoverflow 上类似问题的答案之一找到了以下代码,但是,我需要知道如何访问 keychainUtils 和 IDManager? 提前感谢您的帮助。

+ (NSString *) getUniqueUUID {
    NSError * error;
    NSString * uuid = [KeychainUtils getPasswordForUsername:USER_NAME   andServiceName:SERVICE_NAME error:&error];
    if (error) {
        NSLog(@"Error geting unique UUID for this device! %@", [error localizedDescription]);
        return nil;
    }
    if (!uuid) {
        DLog(@"No UUID found. Creating a new one.");
        uuid = [IDManager GetUUID];
        uuid = [Util md5String:uuid];
        [KeychainUtils storeUsername:kBuyassUser andPassword:uuid forServiceName:kIdOgBetilngService updateExisting:YES error:&error];
        if (error) {
            NSLog(@"Error geting unique UUID for this device! %@", [error localizedDescription]);
            return nil;
        }
    }
    return uuid;
}

我想提供这个作为解决方案。它不需要第三方代码。如果确实需要,它会读取或写入 KeyChain,因此它比迄今为止提供的解决方案更有效。此外,UUID 会写入钥匙串访问组,以便您可以在应用程序之间共享此 UUID。只需改变kKeyChainVendorIDAccessGroup在方法的开始处。

+(NSUUID *)persistentIdentifierForVendor
{
    static NSString * const kKeyChainVendorID = @"co.cwbrn.PersistentIdentifier";
    static NSString * const kKeyChainVendorIDAccessGroup = @"<AppIdentifier>.<keychain-access-group-identifier>";

    // First, check NSUserDefaults so that we're not hitting the KeyChain every single time
    NSString *uuidString = [[NSUserDefaults standardUserDefaults] stringForKey:kKeyChainVendorIDGroup];
    BOOL vendorIDMissingFromUserDefaults = (uuidString == nil || uuidString.length == 0);

    if (vendorIDMissingFromUserDefaults) {
        // Check to see if a UUID is stored in the KeyChain
        NSDictionary *query = @{
                                (__bridge id)kSecClass:             (__bridge id)kSecClassGenericPassword,
                                (__bridge id)kSecAttrAccount:       kKeyChainVendorID,
                                (__bridge id)kSecAttrService:       kKeyChainVendorID,
                                (__bridge id)kSecAttrAccessGroup:   kKeyChainVendorIDAccessGroup,
                                (__bridge id)kSecMatchLimit:        (__bridge id)kSecMatchLimitOne,
                                (__bridge id)kSecReturnAttributes:  (__bridge id)kCFBooleanTrue
                               };
        CFTypeRef attributesRef = NULL;
        OSStatus result = SecItemCopyMatching((__bridge CFDictionaryRef)query, &attributesRef);
        if (result == noErr) {
            // There is a UUID, so try to retrieve it
            NSDictionary *attributes = (__bridge_transfer NSDictionary *)attributesRef;
            NSMutableDictionary *valueQuery = [NSMutableDictionary dictionaryWithDictionary:attributes];

            [valueQuery setObject:(__bridge id)kSecClassGenericPassword  forKey:(__bridge id)kSecClass];
            [valueQuery setObject:(__bridge id)kCFBooleanTrue            forKey:(__bridge id)kSecReturnData];

            CFTypeRef passwordDataRef = NULL;
            OSStatus result = SecItemCopyMatching((__bridge CFDictionaryRef)valueQuery, &passwordDataRef);
            if (result == noErr) {
                NSData *passwordData = (__bridge_transfer NSData *)passwordDataRef;
                uuidString = [[NSString alloc] initWithBytes:[passwordData bytes]
                                                      length:[passwordData length]
                                                    encoding:NSUTF8StringEncoding];
            }
        }
    }

    // Failed to read the UUID from the KeyChain, so create a new UUID and store it
    if (uuidString == nil || uuidString.length == 0) {
        // Generate the new UIID
        CFUUIDRef uuidRef = CFUUIDCreate(kCFAllocatorDefault);
        uuidString = (__bridge_transfer NSString *)CFUUIDCreateString(kCFAllocatorDefault, uuidRef);
        CFRelease(uuidRef);

        // Now store it in the KeyChain
        NSDictionary *query = @{    (__bridge id)kSecClass:             (__bridge id)kSecClassGenericPassword,
                                    (__bridge id)kSecAttrAccount:       kKeyChainVendorID,
                                    (__bridge id)kSecAttrService:       kKeyChainVendorID,
                                    (__bridge id)kSecAttrAccessGroup:   kKeyChainVendorIDAccessGroup,
                                    (__bridge id)kSecAttrLabel:         @"",
                                    (__bridge id)kSecAttrDescription:   @"",
                                    (__bridge id)kSecAttrAccessible:    (__bridge id)kSecAttrAccessibleAfterFirstUnlock,
                                    (__bridge id)kSecValueData:         [uuidString dataUsingEncoding:NSUTF8StringEncoding]
                                };

        OSStatus result = SecItemAdd((__bridge CFDictionaryRef)query, NULL);
        if (result != noErr) {
            NSLog(@"ERROR: Couldn't add to the Keychain. Result = %ld; Query = %@", result, query);
            return nil;
        }
    }

    // Save UUID to NSUserDefaults so that we can avoid the KeyChain next time
    if (vendorIDMissingFromUserDefaults) {
        [[NSUserDefaults standardUserDefaults] setObject:uuidString forKey:kKeyChainVendorIDGroup];
    }

    return [[NSUUID alloc] initWithUUIDString:uuidString];
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将唯一 ID 实现为 UUID 并将其保存在 Keychain 中 的相关文章

  • MapKit 注释未显示在地图上

    我无法让 MKAnnotationViews 显示在 MapKit 的地图上 我正在使用 iOS 7 现在已经在论坛和网络上搜索了很多小时 尝试不同的示例和设置 下面我有 我认为 使其工作的最基本的设置 该应用程序包含一个 ViewCont
  • 在 Swift 4 中在 Google 地图上显示路径

    我的问题是我想绘制两点之间的时间 并且我的两个位置都来自不同的控制器 for my first Location extension HomeViewController PickupLocationDelegate func didSel
  • 如何将任意颜色的色度键滤镜应用到实时摄像头源ios?

    基本上我想将色度键滤镜应用到 ios 实时摄像头源 但我希望用户选择将被另一种颜色替换的颜色 我找到了一些使用绿屏的示例 但我不知道如何动态替换颜色而不仅仅是绿色 知道如何以最佳性能实现这一目标吗 您之前曾询问过我的情况GPUImage h
  • 点击后退按钮时,iCarousel 会显示在上一页

    当我按下后退按钮时 这iCarousel仍然显示 1 秒 为什么会发生这种情况以及如何阻止这种情况 我已经使用故事板创建了 iCarosel 视图 void viewDidUnload super viewDidUnload self ca
  • 如何在iOS应用程序中实现信号量?

    是否可以在ios应用程序中实现计数信号量 对的 这是可能的 有很多可用的同步工具 同步 NSLock NS条件 NS条件锁 GCD 信号量 并行线程锁 我建议阅读 线程编程指南 http developer apple com librar
  • 我如何知道我的 iOS 应用程序的蜂窝网络访问是否被禁用?

    我有一个 iOS 应用程序 它在应用程序启动时发出一些小型网络请求 资源更新等 如果用户在 iOS 设置中关闭应用程序的蜂窝网络访问 他们每次启动时都会收到 iOS 的有关网络使用情况的提示 有没有办法以编程方式知道此应用程序的蜂窝数据已被
  • CALayerframe.size不等于bounds.size

    我在CALayer上遇到了一些奇怪的事情 最后发现CALayer的frame size不等于它的bounds size 这是我无法理解的 我知道frame是在super的坐标系中 bounds是它自己的坐标 并且通常的情况是frame or
  • 从核心数据存储创建 .sqlite 文件?

    我在书籍和提供 sqlite 文件下载的网站上看到过教程 sqlite 文件用于核心数据 如何获取 sqlite 文件FROM应用程序或核心数据存储TO我的桌面 如果您要创建一个预填充的 sqlite 文件以与 Core Data 一起使用
  • 将 NSData 视频文件合并为一个视频文件

    我有一堆视频文件想要合并成一个视频文件 我正在使用 NSMutableData 来完成该任务 NSMutableData concatenatedData NSMutableData alloc init for int i 0 i lt
  • 在 iPhone 5 的横向模式下启动启动画面

    我们的通用应用程序仅适用于横向模式 我们需要为 iPhone 4 和 iPhone 5 添加启动画面 对于 iPhone 5 的肖像 我们使用 email protected cdn cgi l email protection 如何为 i
  • Swift 中的自定义输入视图

    我花了几个小时试图弄清楚如何创建 然后定制inputView上班 我有一个网格TextInputs 想想拼字板 按下时应该加载自定义inputView插入文本 我创建了一个 xib文件包含UI elements为定制inputView 我能
  • UIView 内的 UIButton 目标操作

    我有一个习惯UIView我创建了一个UIButton 在该视图中 我有以下代码 func setupViews menuControlButton addTarget self action toggleButton forControlE
  • 如何安全地将 CGFloat 降低或提高到 int?

    我经常需要在地板或天花板上安装CGFloat to an int 用于计算数组索引 我永远看到的问题floorf theCGFloat or ceilf theCGFloat 是浮点不准确可能会带来麻烦 那如果我的CGFloat is 2
  • 如何在WKInterfaceLabel下面放置一个WKInterfaceLabel?

    大家好 我在 watchkit 开发中有新的东西 我有特殊要求 我将一个 WKInterfaceLabel 安排在另一个 WKInterfaceLabel 下面 我尝试使用很多关闭选项 例如编辑位置 但 WKInterfaceLabel 未
  • xCode 7.1 中警报的 UITesting

    我正在 xCode 7 1 中编写 UITests 并且在测试警报时遇到问题 在我的情况下允许通知 创建测试时 xCode 会写入以下代码 app alerts U201cAppName U201d Would Like to Send Y
  • 空 NSDatePicker

    你好 是否可以让 NSDatePicker 代表 nil 对象 类似 或任何其他方式 谢谢 拉杜 简短回答 否 NSDatePicker 只是忽略无效日期和 nil 例如 这不会更新 NSDatePicker 旧值仍然存在 datePick
  • 从 iOS 中的 App Delegate 调用当前视图控制器中的方法

    我有两个视图控制器 BuildingsViewController 和 RoomsViewController 它们都使用应用程序委托中名为上传的函数 上传函数基本上执行一个 HTTP 请求 如果成功或不成功 都会触发 uialertvie
  • 如何将图像放在 UIButton 中文本的右侧?

    如果可以避免的话 我不想使用子视图 我想要一个UIButton其中包含背景图像 文本和图像 现在 当我这样做时 图像位于文本的左侧 背景图像 文本和图像都有不同的高亮状态 最简单的解决方案 iOS 10 及更高版本 Swift button
  • Swift 中的 AURenderCallback

    我正在创建一个使用音频单元的应用程序 虽然 Objective C 中有很多代码示例 包括 Apple 自己的 aurioTouch 等 但我正在尝试用 Swift 编写整个代码 我已经能够设置我的 AUGraph 并通过它运行一些音频 但
  • cocos2d 2.0-rc2:结束director并重新启动

    我有一款由 cocos2d 驱动的游戏 它使用 UIKit 菜单 所以我只使用一个视图控制器的框架 即游戏本身 而且 它只有一个场景 从cocos2d 2 0开始 director本身就是一个UIViewController子类 所以我只是

随机推荐

  • Ubuntu 中的 Eclipse:悬停背景颜色属性在哪里?

    我更改了悬停代码时可见的背景颜色 黑色 例如 当您将鼠标悬停在某个方法上时 您会在一个框中看到其签名 我的意思是那个盒子的背景颜色 我想更改它 但我在任何地方都找不到该属性 你知道它是什么财产吗 它应该是一个全球财产 因为其他框使用相同的背
  • 检查三个布尔值中是否至少有两个为 true

    最近一位面试官问了我这个问题 给定三个布尔变量 a b 和 c 如果三个中至少有两个为 true 则返回 true 我的解决方案如下 boolean atLeastTwo boolean a boolean b boolean c if a
  • Array.prototype.sort() 时间复杂度是多少?

    根据 Mozilla 文档 无法保证排序的时间复杂度和空间复杂度 取决于实施 至少可以安全地假设它不是O n 2 有没有关于它如何实施的更详细的数据 谢谢 火狐使用归并排序 https medium com nandodrw merge s
  • Magento Mage::getUrl 带后缀

    当 url 具有 html 后缀时 在 magento 中处理生成 url 的正确方法是什么 例如 获取以下产品 url 类别 产品 html 你不能简单地做Mage getUrl mycategory myproduct html or
  • 通过填充 UIImageView 图层边框宽度的颜色来动画进度

    我有 UIImageView 我把它做成了带有宽度层的圆形 如下图所示 用户可以更新图像并上传新图像 上传图像时我有一个进度回调 我想要的是在上传图像时用颜色对边框进行动画处理 例如 当用户单击上传时 边框从顶部开始为绿色 并根据进度填充宽
  • 自定义函数缺少参数 2

    因此 我尝试在保存更改后将原始的 post title 替换为同一篇文章右侧的自定义字段 但是 我在帖子页面上收到以下错误 警告 第 113 行 PATH public html wp content themes THEME functi
  • Chocolatey的正确使用(包更新/版本管理)

    注意 这个问题对于 Chocolatey 0 9 8 及以下版本有效 后来的版本从PowerShell脚本完全重写为C 应用程序 并且包管理的整个过程得到了很大的改进 我一直在使用巧克力味一段时间了 一开始我很兴奋 但过了一段时间我不确定它
  • 收到无效的 JSON 负载。未知名称 click_action

    所以我目前正在开发一个 PWA 我现在正在与推送通知我已经能够使用以下非常简单的 JSON 结构接收后台和前台通知 message token aValidToken notification title New Content body
  • 拦截MEF中的依赖关系

    是否可以在 MEF 处理依赖项请求之前拦截 MEF 中的依赖项请求 这对于实现装饰器和高级生命周期管理非常有用 就像是 catalogue AddInterceptor
  • 如何区分“消息”更新和“回调查询”更新? (电报机器人 API)

    抱歉 如果我的问题太混乱了 我是新来的 所以欢迎任何建议 如何区分 消息 更新和 回调查询 更新 我已经成功制作了一个内联键盘 但是当我使用它时 机器人只是挂起 他没有回复任何内容 我做了一些研究发现这个问题 https stackover
  • 错误:解析 XML 时出错:格式不正确(令牌无效)...?

    我正在开发一个具有以下 XML 的应用程序 但是当我尝试清理 构建我的项目时 会发生以下错误 错误 解析 XML 时出错 格式不正确 令牌无效
  • 检测控制台应用程序中的按键?

    我需要在控制台应用程序中检测按键 而不提示用户 基本上 我的应用程序通常是一个监听特殊输入设备的守护进程 但我需要在交互模式下使用键盘在开发盒上模拟它 我怎样才能做到这一点 我在 Linux 系统上 如果您在等待输入时无法阻塞 那么您可以使
  • 如何识别 Openoffice Calc 中两列中的重复值

    我有两列 其中有数字 当另一个人有重复的数字时 另一个人只拥有一次该数字 这些列中的数字不匹配 我需要找到 B 列中与 A 列中匹配的所有数字 这可能更好地解释了它 A B 1 2 2 2 4 5 6 5 7 6 8 6 我想得到这样的结果
  • 防止对 Web 应用程序的字典攻击

    防止字典攻击的最佳方法是什么 我已经想到了几种实现方式 但它们似乎都存在一些缺陷 X 次登录尝试失败后锁定用户 问题 很容易变成拒绝服务攻击 在短时间内锁定许多用户 逐渐增加用户名每次登录尝试失败的响应时间 问题 字典攻击可能使用相同的密码
  • 如何从指令获取角度视图层次结构?

    角度版本 6 我正在研究一个可以放置在任何元素上的指令 以用于一般使用日志记录 对于上下文 它看起来类似于以下内容 Directive selector log export class LogDirective Input log str
  • 替换 Woocommerce 3.4 中的 woocommerce_add_order_item_meta 挂钩

    我有自定义代码使用 woocommerce add order item meta 挂钩 但 woocommerce 3 4 0 显示错误日志 自版本 3 0 0 起 woocommerce add order item meta 已弃用
  • StoreKit 的 SKStoreProductViewController 在导航栏和视图之间留有空间?

    我有 UIViewController 的子类 它显示SKStoreProductViewController 该视图控制器最初是为 iOS 5 创建的 不使用自动布局 我的问题是 当SKStoreProductViewController
  • Phonegap:在 Android 中调整键盘显示上的 webview 大小

    我有一个类似的模态 有固定定位 Facebook 在最新的 Android 版本中对 Messenger 中的 feed chat 中的评论有何评论 我想要的看起来类似于 因此 当您专注于输入时 键盘会打开并缩小网络视图 默认情况下它不起作
  • 如何检查 YouTube 上是否存在某个频道?

    如果我做一个curl请求此网址 https www googleapis com youtube v3 channels part snippet 2CcontentDetails 2Cstatistics id UC x5XG1OVP6u
  • 将唯一 ID 实现为 UUID 并将其保存在 Keychain 中

    我的应用程序中需要唯一 ID 我知道 我们不能再使用 UDID 因此根据我的研究 使用 UUID 作为设备唯一 ID 并将其保存在钥匙串中将确保即使用户重新安装我的应用程序 唯一 ID 仍保持不变 我从 stackoverflow 上类似问