I’m encountering a recurring crash in my iOS app that appears to be associated to reminiscence allocation when accessing Keychain objects. The stack hint signifies points with reminiscence allocation and object creation throughout the execution of the readValue methodology from my KeychainItem module, which is used to fetch and decode values from the Keychain.
I’ve offered the related code snippets for the readValue and save strategies under. The error factors to the crash occurring on the line the place decoding the info retrieved from the Keychain is tried.
Might somebody please assist me perceive what may be inflicting this situation and the way I might resolve it to forestall the crash?
Any insights, recommendations, or debugging ideas can be vastly appreciated. Thanks prematurely!
`func readValue<T: Codable>(object: T.Sort) throws -> T? {
lock.lock()
defer { lock.unlock() }
var question = KeychainItem.keychainQuery(withService: service, key: key, accessGroup: accessGroup)
question[kSecMatchLimit as String] = kSecMatchLimitOne
question[kSecReturnAttributes as String] = kCFBooleanTrue
question[kSecReturnData as String] = kCFBooleanTrue
var queryResult: AnyObject?
let standing = withUnsafeMutablePointer(to: &queryResult) {
SecItemCopyMatching(question as CFDictionary, $0)
}
guard standing != errSecItemNotFound else { throw KeychainError.noData }
guard standing == noErr else { throw KeychainError.unhandledError(standing: standing) }
guard let existingItem = queryResult as? [String: AnyObject],
let keychainData = existingItem[kSecValueData as String] as? Information else {
throw KeychainError.unexpectedData
}
if let knowledge = attempt? PropertyListDecoder().decode(object, from: keychainData) {
return knowledge
}
return String(knowledge: keychainData, encoding: .utf8) as? T
}
func save<T: Codable>(_ object: T) throws {
let encodedData: Information
if let obj = object as? String {
encodedData = obj.knowledge(utilizing: .utf8) ?? Information()
} else {
encodedData = attempt PropertyListEncoder().encode(object)
}
do {
attempt _ = readValue(object: T.self)
var attributesToUpdate = [String: AnyObject]()
attributesToUpdate[kSecValueData as String] = encodedData as AnyObject?
let question = KeychainItem.keychainQuery(withService: service, key: key, accessGroup: accessGroup)
let standing = SecItemUpdate(question as CFDictionary, attributesToUpdate as CFDictionary)
guard standing == noErr else { throw KeychainError.unhandledError(standing: standing) }
} catch KeychainError.noData {
var newItem = KeychainItem.keychainQuery(withService: service, key: key, accessGroup: accessGroup)
newItem[kSecValueData as String] = encodedData as AnyObject?
let standing = SecItemAdd(newItem as CFDictionary, nil)
guard standing == noErr else { throw KeychainError.unhandledError(standing: standing) }
}
}`
What i am attempting to do is retrieving Opaque Consumer ID from keychain utilizing these strategies, and it calls the readValue and save capabilities in KeyChainItem Module
` class func latestId() -> String? {
if let idsDict = attempt? KeychainItem(key: idsArrayKey).readValue(object: [String: String].self) {
let sortedKeys = Array(idsDict.keys).sorted(by: <)
if let lastKey = sortedKeys.final {
return idsDict[lastKey]
}
} else {
updateID()
}
return self.latestId()
}
non-public class func updateID() {
let id = UUID().uuidString
let timestamp = Date().timeIntervalSince1970.description
// Append dictionaries if attainable
if let idsDict = attempt? KeychainItem(key: idsArrayKey).readValue(object: [String: String].self) {
let generalDict = idsDict.merging([timestamp: id]) { (_, new) in new }
attempt? KeychainItem(key: idsArrayKey).save(generalDict)
} else {
attempt? KeychainItem(key: idsArrayKey).save([timestamp: id])
}
attempt? KeychainItem(key: idsLastUpdateKey).save(timestamp)
delegate?.didGenerateOpaqueId(id)
}`