我试图读取钥匙串,但文档警告我如下:
SecItemCopyMatching 会阻塞调用线程,因此如果从主线程调用它,可能会导致应用程序的 UI 假死。相反,应该从后台调度队列或异步函数中调用 SecItemCopyMatching。 来源 因此,我想编写一个在后台运行的异步方法。
我的问题是,这位演员已经将其设为线程安全了吗?
通常我会添加一个 NSLock 来保证安全。
然而,现在我收到一个警告:
那么,我该如何解决这个问题?
SecItemCopyMatching 会阻塞调用线程,因此如果从主线程调用它,可能会导致应用程序的 UI 假死。相反,应该从后台调度队列或异步函数中调用 SecItemCopyMatching。 来源 因此,我想编写一个在后台运行的异步方法。
actor Keychain {
public static let standard = Keychain()
public enum Error: Swift.Error {
case failed(String)
}
public func get(_ key: String) async throws -> Data? {
let backgroundTask = Task(priority: .background) {
var query: [String: Any] = [
type(of: self).klass : kSecClassGenericPassword,
type(of: self).attrAccount : key,
type(of: self).matchLimit : kSecMatchLimitOne,
type(of: self).returnData : kCFBooleanTrue as CFBoolean
]
var item: CFTypeRef?
let status = SecItemCopyMatching(query as CFDictionary, &item)
guard status == errSecSuccess else {
if let errorMessage = SecCopyErrorMessageString(status, nil) {
throw Error.failed(String(errorMessage))
} else {
throw Error.failed("unsupported")
}
}
return item as? Data
}
return try await backgroundTask.value
}
}
我的问题是,这位演员已经将其设为线程安全了吗?
通常我会添加一个 NSLock 来保证安全。
public func get(_ key: String) async throws -> Data? {
lock.lock()
defer { lock.unlock() }
(...)
return try await task.value
}
然而,现在我收到一个警告:
Instance method 'lock' is unavailable from asynchronous contexts; Use async-safe scoped locking instead; this is an error in Swift 6
。那么,我该如何解决这个问题?