From 0a44232e907d60f4fba065cfdd4aa969912ac264 Mon Sep 17 00:00:00 2001 From: vinkwok Date: Thu, 11 Aug 2022 10:39:11 +0800 Subject: [PATCH] Major Keychain helper cleanup Run blocking operations on the utility DispatchQueue to prevent hanging the main thread --- Swiftcord/Utils/Keychain.swift | 66 +++++++++++++++++++--------------- 1 file changed, 37 insertions(+), 29 deletions(-) diff --git a/Swiftcord/Utils/Keychain.swift b/Swiftcord/Utils/Keychain.swift index b0f4b2fe..ea342612 100644 --- a/Swiftcord/Utils/Keychain.swift +++ b/Swiftcord/Utils/Keychain.swift @@ -10,37 +10,32 @@ import Foundation import Security public class Keychain { - static let tag = Bundle.main.bundleIdentifier!.data(using: .utf8)! + private static let tag = Bundle.main.bundleIdentifier!.data(using: .utf8)! @discardableResult - public class func save(key: String, data: String) -> OSStatus { - return save(key: key, data: data.data(using: .utf8)!) - } - - @discardableResult - public class func save(key: String, data: Data) -> OSStatus { + fileprivate class func _save(key: String, data: Data) -> OSStatus { let query = [ - kSecClass as String: kSecClassGenericPassword as String, - kSecAttrAccount as String: "\(Bundle.main.bundleIdentifier!).\(key)", - kSecAttrApplicationTag as String: tag, - kSecValueData as String: data - ] as [String: Any] + kSecClass: kSecClassGenericPassword, + kSecAttrAccount: "\(Bundle.main.bundleIdentifier!).\(key)", + kSecAttrApplicationTag: tag, + kSecValueData: data + ] as CFDictionary - SecItemDelete(query as CFDictionary) + SecItemDelete(query) - return SecItemAdd(query as CFDictionary, nil) + return SecItemAdd(query, nil) } @discardableResult - public class func remove(key: String) -> OSStatus { + fileprivate class func _remove(key: String) -> OSStatus { let query = [ - kSecClass as String: kSecClassGenericPassword as String, - kSecAttrAccount as String: "\(Bundle.main.bundleIdentifier!).\(key)", - kSecAttrApplicationTag as String: tag, - kSecMatchLimit as String: kSecMatchLimitOne - ] as [String: Any] + kSecClass: kSecClassGenericPassword, + kSecAttrAccount: "\(Bundle.main.bundleIdentifier!).\(key)", + kSecAttrApplicationTag: tag, + kSecMatchLimit: kSecMatchLimitOne + ] as CFDictionary - return SecItemDelete(query as CFDictionary) + return SecItemDelete(query) } public class func load(key: String) -> String? { @@ -50,22 +45,22 @@ public class Keychain { public class func loadData(key: String) -> Data? { let query = [ - kSecClass as String: kSecClassGenericPassword, - kSecAttrAccount as String: "\(Bundle.main.bundleIdentifier!).\(key)", - kSecReturnData as String: kCFBooleanTrue!, - kSecAttrApplicationTag as String: tag, - kSecMatchLimit as String: kSecMatchLimitOne - ] as [String: Any] + kSecClass: kSecClassGenericPassword, + kSecAttrAccount: "\(Bundle.main.bundleIdentifier!).\(key)", + kSecReturnData: true, + kSecAttrApplicationTag: tag, + kSecMatchLimit: kSecMatchLimitOne + ] as CFDictionary var dataTypeRef: AnyObject? - let status: OSStatus = SecItemCopyMatching(query as CFDictionary, &dataTypeRef) + let status: OSStatus = SecItemCopyMatching(query, &dataTypeRef) guard status == noErr else { return nil } return dataTypeRef as? Data } - public class func createUniqueID() -> String { + private class func createUniqueID() -> String { let uuid: CFUUID = CFUUIDCreate(nil) let cfStr: CFString = CFUUIDCreateString(nil, uuid) @@ -74,6 +69,19 @@ public class Keychain { } } +// Publically exposed methods +public extension Keychain { + class func save(key: String, data: String) { + save(key: key, data: data.data(using: .utf8)!) + } + static func save(key: String, data: Data, canSync: Bool = true) { + DispatchQueue.global(qos: .utility).async { _save(key: key, data: data) } + } + static func remove(key: String) { + DispatchQueue.global(qos: .utility).async { _remove(key: key) } + } +} + public extension Data { init(from value: T) { var value = value