如何使非可发送类型在可发送上下文中可用?



我有这样的代码

public func webView(
_ webView: WKWebView,
didReceive challenge: URLAuthenticationChallenge,
completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void
) {

Task.detached(priority: .background) {
guard let serverTrust = challenge.protectionSpace.serverTrust else {
completionHandler(.cancelAuthenticationChallenge, nil)
return
}
let exceptions = SecTrustCopyExceptions(serverTrust)
SecTrustSetExceptions(serverTrust, exceptions)
completionHandler(.useCredential, URLCredential(trust: serverTrust))
}
}

但是Xcode抱怨URLAuthenticationChallenge类型是不可发送的如何使此类型可发送,或将其传递给task并提供多线程安全访问

我做过这样的事情

struct SendableValue<T> {
let value: T
}

警告消失了,但我怀疑这是正确的解决方案,因为没有任何互斥

也许应该更像这样

struct SendableValue<T>: Sendable {
private let semaphore = DispatchSemaphore(value: 1)
private var _value: T

init(value: T) {
_value = value
}

var value: T {
get {
semaphore.wait()
defer { semaphore.signal() }
return _value
}
set {
semaphore.wait()
defer { semaphore.signal() }
_value = newValue
}
}
}

但是在此类型上添加Sendable的一致性会抛出另一个警告

也许我不应该遵循Sendable

我想我这里做错了什么。

是否有任何通用的简单方法从第三方库为非Sendable类型提供隔离层,使其在多并发环境中可Sendable即安全?

我想你可以试试@unchecked,然后warpchallenge.protectionSpace.serverTrust

struct SendableURLAuthenticationChallenge: @unchecked Sendable {
private let semaphore = DispatchSemaphore(value: 1)
private var challenge: URLAuthenticationChallenge

init(value: URLAuthenticationChallenge) {
challenge = value
}

var trust: SecTrust? {
semaphore.wait()
defer { semaphore.signal() }
return challenge.protectionSpace.serverTrust
}
}

public func webView(
_ webView: WKWebView,
didReceive challenge: URLAuthenticationChallenge,
completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void
) {
let sendabelChallenge = SendableURLAuthenticationChallenge(value: challenge)

Task.detached(priority: .background) {
guard let serverTrust = sendabelChallenge.trust else {
completionHandler(.cancelAuthenticationChallenge, nil)
return
}
let exceptions = SecTrustCopyExceptions(serverTrust)
SecTrustSetExceptions(serverTrust, exceptions)
completionHandler(.useCredential, URLCredential(trust: serverTrust))
}
}

但是在异步函数中使用同步机制确实很危险,需要仔细测试

最新更新