使用自定义错误在withCheckedThrowingContinuation中。

huangapple go评论80阅读模式
英文:

Using custom error in withCheckedThrowingContinuation

问题

enum FooError : Error {}

class FooTest {
func slowMethod() async throws {
try await withCheckedThrowingContinuation { (c: CheckedContinuation<Void, FooError>) -> Void in
}
}
}

获取到以下编译错误:
无法将类型为 '(CheckedContinuation<Void, FooError>) -> Void' 的值转换为预期的参数类型 '(CheckedContinuation<Void, any Error>) -> Void'。泛型参数 'E'('any Error' 和 'FooError')预期应该相等

withCheckedThrowingContinuation 能够接受自定义错误吗?

编辑

根据下面的评论,这种方式也不起作用:

enum FooError : Error {}

class FooTest {
    func slowMethod() async throws {
        try await withCheckedThrowingContinuation { (c: CheckedContinuation<Void, Error>) -> Void in
            c.resume(throwing: FooError)
        }
    }
}

给出的错误是:
参数类型 'FooError.Type' 不符合预期类型 'Error'

英文:

I am unable to cause Xcode to accept the following code.

enum FooError : Error {}

class FooTest {
    func slowMethod() async throws {
        try await withCheckedThrowingContinuation { (c: CheckedContinuation&lt;Void, FooError&gt;) -&gt; Void in
        }
    }
}

Getting the following compilation error:
Cannot convert value of type &#39;(CheckedContinuation&lt;Void, FooError&gt;) -&gt; Void&#39; to expected argument type &#39;(CheckedContinuation&lt;Void, any Error&gt;) -&gt; Void&#39;. Arguments to generic parameter &#39;E&#39; (&#39;any Error&#39; and &#39;FooError&#39;) are expected to be equal

Is it possible for withCheckedThrowingContinuation to accept custom errors?

Edit

Following the comments below, this does not work either:

enum FooError : Error {}

class FooTest {
    func slowMethod() async throws {
        try await withCheckedThrowingContinuation { (c: CheckedContinuation&lt;Void, Error&gt;) -&gt; Void in
            c.resume(throwing: FooError)
        }
    }
}

The error given is:
Argument type &#39;FooError.Type&#39; does not conform to expected type &#39;Error&#39;

答案1

得分: 1

enum FooError : Error {} // 单独这样写表示任何 Type FooError 的 value 都将符合 Error 协议

FooError 本身是一个 Type 而不是一个 value

要获取一个 value,在处理枚举时需要使用 case

enum FooError : Error {
case someValueHere //这是一个 value
}

最终的代码看起来应该像这样。

actor FooTest {
func slowMethod() async throws {
try await withUnsafeThrowingContinuation({ (c: UnsafeContinuation<Void, Error>) in
c.resume(throwing: FooError.someValueHere)
})
}
}

请注意,由于返回类型是 Void,我正在使用 withUnsafeThrowingContinuation

withCheckedThrowingContinuation 期望你调用 c.resume(/* 一些返回值 */)

如果使用 LocalizedError,你可以提取第二个 Error

enum FooError : LocalizedError {
case someValueHere //这是一个 value
case bar(_ innerError: Error)

var errorDescription: String?{
    switch self {
    case .bar(let error):
        let nsError = error as NSError
        return nsError.localizedDescription
    default:
        return "\(self)".localizedCapitalized
    }
}
var failureReason: String?{
    switch self {
    case .bar(let error):
        let nsError = error as NSError
        return nsError.localizedFailureReason
    default:
        return nil
    }
}
var helpAnchor: String? {
    switch self {
    case .bar(let error):
        let nsError = error as NSError
        return nsError.helpAnchor
    default:
        return nil
    }
}
var recoverySuggestion: String? {
    switch self {
    case .bar(let error):
        let nsError = error as NSError
        return nsError.localizedRecoverySuggestion
    default:
        return nil
    }
}

}

英文:

I think you are misunderstanding some basics.

enum FooError : Error {} // This on its own says that any `value` of `Type` FooError will conform to Error

FooError by itself is a Type not a value.

Now to get a value you need a case when dealing with an enum

enum FooError : Error {
    case someValueHere //This is a value
}

With your final code looking something like.

actor FooTest {
    func slowMethod() async throws  {
        try await withUnsafeThrowingContinuation({ (c: UnsafeContinuation&lt;Void, Error&gt;) in
            c.resume(throwing: FooError.someValueHere)
        })
    }
}

Notice that since the return is a Void I am using withUnsafeThrowingContinuation

withCheckedThrowingContinuation expect you to call c.resume(/* some return value */)

You can extract a secondary Error if you use LocalizedError

enum FooError : LocalizedError {
    case someValueHere //This is a value
    case bar(_ innerError: Error)
    
    var errorDescription: String?{
        switch self {
        case .bar(let error):
            let nsError = error as NSError
            return nsError.localizedDescription
        default:
            return &quot;\(self)&quot;.localizedCapitalized
        }
    }
    var failureReason: String?{
        switch self {
        case .bar(let error):
            let nsError = error as NSError
            return nsError.localizedFailureReason
        default:
            return nil
        }
    }
    var helpAnchor: String? {
        switch self {
        case .bar(let error):
            let nsError = error as NSError
            return nsError.helpAnchor
        default:
            return nil
        }
    }
    var recoverySuggestion: String? {
        switch self {
        case .bar(let error):
            let nsError = error as NSError
            return nsError.localizedRecoverySuggestion
        default:
            return nil
        }
    }

}

huangapple
  • 本文由 发表于 2023年6月5日 17:28:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/76405083.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定