gpt4 book ai didi

swift - 如何快速获取真正固定的 Device-ID?

转载 作者:搜寻专家 更新时间:2023-11-01 05:49:28 71 4
gpt4 key购买 nike

我长期以来一直使用下面的代码。我以为它是独一无二的

但是我删除了我的应用程序并重新安装了它,我得到了新的不同的设备 ID。

if let uuid = UIDevice.current.identifierForVendor?.uuidString {
print(uuid)
}

每次重新安装,我都会得到一个新 ID。

我如何获得保持不变的东西?

最佳答案

由于从 identifierForVendor 返回的值可以在删除应用程序时被清除,或者如果用户在“设置”应用程序中重置它,则可以重置它,因此您必须自己管理持久化。

有几种方法可以实现这一点。您可以设置一个分配 uuid 的服务器,然后通过用户登录持久保存并获取服务器端,或者您可以在本地创建并将其存储在钥匙串(keychain)中。

存储在钥匙串(keychain)中的项目不会在删除应用程序时被删除。这允许您检查以前是否存储了 uuid,如果是,您可以检索它,如果不是,您可以生成一个新的 uuid 并保留它。

您可以通过以下方式在本地执行此操作:

/// Creates a new unique user identifier or retrieves the last one created
func getUUID() -> String? {

// create a keychain helper instance
let keychain = KeychainAccess()

// this is the key we'll use to store the uuid in the keychain
let uuidKey = "com.myorg.myappid.unique_uuid"

// check if we already have a uuid stored, if so return it
if let uuid = try? keychain.queryKeychainData(itemKey: uuidKey), uuid != nil {
return uuid
}

// generate a new id
guard let newId = UIDevice.current.identifierForVendor?.uuidString else {
return nil
}

// store new identifier in keychain
try? keychain.addKeychainData(itemKey: uuidKey, itemValue: newId)

// return new id
return newId
}

这是用于从钥匙串(keychain)中存储/​​检索的类:

import Foundation

class KeychainAccess {

func addKeychainData(itemKey: String, itemValue: String) throws {
guard let valueData = itemValue.data(using: .utf8) else {
print("Keychain: Unable to store data, invalid input - key: \(itemKey), value: \(itemValue)")
return
}

//delete old value if stored first
do {
try deleteKeychainData(itemKey: itemKey)
} catch {
print("Keychain: nothing to delete...")
}

let queryAdd: [String: AnyObject] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: itemKey as AnyObject,
kSecValueData as String: valueData as AnyObject,
kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlocked
]
let resultCode: OSStatus = SecItemAdd(queryAdd as CFDictionary, nil)

if resultCode != 0 {
print("Keychain: value not added - Error: \(resultCode)")
} else {
print("Keychain: value added successfully")
}
}

func deleteKeychainData(itemKey: String) throws {
let queryDelete: [String: AnyObject] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: itemKey as AnyObject
]

let resultCodeDelete = SecItemDelete(queryDelete as CFDictionary)

if resultCodeDelete != 0 {
print("Keychain: unable to delete from keychain: \(resultCodeDelete)")
} else {
print("Keychain: successfully deleted item")
}
}

func queryKeychainData (itemKey: String) throws -> String? {
let queryLoad: [String: AnyObject] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: itemKey as AnyObject,
kSecReturnData as String: kCFBooleanTrue,
kSecMatchLimit as String: kSecMatchLimitOne
]
var result: AnyObject?
let resultCodeLoad = withUnsafeMutablePointer(to: &result) {
SecItemCopyMatching(queryLoad as CFDictionary, UnsafeMutablePointer($0))
}

if resultCodeLoad != 0 {
print("Keychain: unable to load data - \(resultCodeLoad)")
return nil
}

guard let resultVal = result as? NSData, let keyValue = NSString(data: resultVal as Data, encoding: String.Encoding.utf8.rawValue) as String? else {
print("Keychain: error parsing keychain result - \(resultCodeLoad)")
return nil
}
return keyValue
}
}

然后你可以只拥有一个用户类,你可以在其中获取标识符:

let uuid = getUUID()
print("UUID: \(uuid)")

如果您将它放在 viewDidLoad 的测试应用中,启动该应用并记下控制台中打印的 uuid,删除该应用并重新启动,您将拥有相同的 uuid。

如果您愿意,您也可以在应用程序中创建您自己的完全自定义的 uuid,方法如下:

// convenience extension for creating an MD5 hash from a string
extension String {

func MD5() -> Data? {
guard let messageData = data(using: .utf8) else { return nil }

var digestData = Data(count: Int(CC_MD5_DIGEST_LENGTH))
_ = digestData.withUnsafeMutableBytes { digestBytes in
messageData.withUnsafeBytes { messageBytes in
CC_MD5(messageBytes, CC_LONG(messageData.count), digestBytes)
}
}

return digestData
}
}

// extension on UUID to generate your own custom UUID
extension UUID {

static func custom() -> String? {
guard let bundleID = Bundle.main.infoDictionary?["CFBundleIdentifier"] as? String else {
return nil
}

let unique = bundleID + NSUUID().uuidString
let hashData = unique.MD5()
let md5String = hashData?.map { String(format: "%02hhx", $0) }.joined()

return md5String
}
}

请注意,要使用 MD5 函数,您必须将以下导入添加到应用程序中的 Objective-C 桥接 header :(如果您使用 Xcode < 10 进行构建。在 Xcode 10+ 中包含 CommonCrypto所以你可以跳过这一步)

#import <CommonCrypto/CommonCrypto.h>

如果您的应用没有桥接 header ,请将一个桥接 header 添加到您的项目中,并确保在build设置中进行设置:

Screenshot

设置完成后,您可以像这样生成自己的自定义 uuid:

let otherUuid = UUID.custom()
print("Other: \(otherUuid)")

运行应用程序并记录两个输出会生成类似这样的 uuid:

// uuid from first example
UUID: Optional("8A2496F0-EFD0-4723-8C6D-8E18431A49D2")

// uuid from second custom example
Other: Optional("63674d91f08ec3aaa710f3448dd87818")

关于swift - 如何快速获取真正固定的 Device-ID?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51641614/

71 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com