withUnsafeThrowingContinuation 表达式类型在没有更多上下文的情况下不明确

问题描述 投票:0回答:1

我尝试使用 make @escaping 函数与

withUnsafeThrowingContinuation
进行异步/等待,但出现错误:

如果没有更多上下文,表达类型不明确

代码:

private func asyncUpload() async {
    guard let image = self.manager?.getUserModel()?.image else { return }
    let body = SetAvatarRequest(username: UserManager.shared.username, image: image)
    do {
        try await withUnsafeThrowingContinuation { (continuation: UnsafeContinuation<Void, Error>) in
            RESTClient.shared.uploadImage(
                fileName: "\(UserManager.shared.username)_avatar",
                path: "files/avatar/\(UserManager.shared.userId)",
                body: body) { result in
                    print(result)
                    switch result {
                    case .success:
                        UserManager.shared.setImage(image)
                 continuation.resume(returning: ())
                        self?.removeFromFailed(type: type)
                    case let .failure(error):
                        print("DEBUG: \(error.localizedDescription)")
             continuation.resume(throwing: error)
                    }
                }
        } as Void
    } catch {
        print("error")
    }
}
ios swift asynchronous async-await
1个回答
0
投票

“如果没有更多上下文,表达式类型不明确”错误可能会产生误导,因为它只是告诉您它无法推理代码。在没有看到更多代码的情况下,并不完全清楚问题出在哪里,但是

self?.removeFromFailed(type: type)
非常可疑,因为 (a) 您传递给此函数的值
type
没有在任何地方定义; (b) 您没有
[weak self]
捕获列表,因此
self?
也没有意义。

当我删除该行后,错误就消失了。

private func asyncUpload() async throws {
    guard let image = self.manager?.getUserModel()?.image else { return }
    let body = SetAvatarRequest(username: UserManager.shared.username, image: image)
    do {
        try await withCheckedThrowingContinuation { continuation in
            RESTClient.shared.uploadImage(
                fileName: "\(UserManager.shared.username)_avatar",
                path: "files/avatar/\(UserManager.shared.userId)",
                body: body
            ) { result in
                    print(result)
                    switch result {
                    case .success:
                        UserManager.shared.setImage(image)
                        continuation.resume()
                        // self?.removeFromFailed(type: type)
                    case let .failure(error):
                        print("DEBUG: \(error)")
                        continuation.resume(throwing: error)
                    }
                }
        }
    } catch {
        print(error) // not print("error") … not even sure why you're printing it here given that you printed it above
        throw error
    }
}

现在,我并不是说这个

self?.removeFromFailed(type: type)
一定是错误的根源,但乍一看它是最有可能的候选者。如果这不是问题,请逐行注释掉,以找出闭包内的哪一行使编译器感到困惑。

就我个人而言,我也会消除那些不必要的

catch

private func asyncUpload() async throws {
    guard let image = self.manager?.getUserModel()?.image else { return }
    let body = SetAvatarRequest(username: UserManager.shared.username, image: image)

    try await withCheckedThrowingContinuation { continuation in
        RESTClient.shared.uploadImage(
            fileName: "\(UserManager.shared.username)_avatar",
            path: "files/avatar/\(UserManager.shared.userId)",
            body: body
        ) { result in
            print(result)
            switch result {
            case .success:
                UserManager.shared.setImage(image)
                continuation.resume()
                // self?.removeFromFailed(type: type)
            case let .failure(error):
                print("DEBUG: \(error)")
                continuation.resume(throwing: error)
            }
        }
    }
}

一些不相关的观察结果:

  1. as Void
    是不必要的,我将其删除了。

  2. Apple 建议一般使用

    withCheckedThrowingContinuation
    而不是
    withUnsafeThrowingContinuation

  3. resume(returning: ())
    可以简化为
    resume()

  4. localizedDescription
    中的
    error
    用于UI呈现,但通常不足以用于调试目的。只需打印
    error

  5. 我已将其更改为

    throws
    的方法。作为一般规则,抛出发生的任何错误。好吧,如果调用者想要忽略发生的任何错误,那么好吧,it 可以选择用
    try?
    而不是
    try
    来忽略错误。但这应该是在调用点做出的决定,而不是融入到这个
    asyncUpload
    方法中,恕我直言。

    但是,一般来说,捕获错误而不重新

    throw
    (就像第一个示例一样)是错误的。或者,更简单地说,消除整个
    do
    -
    try
    -
    catch

© www.soinside.com 2019 - 2024. All rights reserved.