没有返回值的Async/Await函数 | Swift 5.5

12
如何在不出现错误的情况下从函数中删除布尔返回值:
Generic parameter 'T' could not be inferred

这是函数:

private func syncDataStore() async throws -> Bool {
    try await withUnsafeThrowingContinuation { continuation in
        Amplify.DataStore.stop { (result) in
            switch(result) {
            case .success:
                Amplify.DataStore.start { (result) in
                    switch(result) {
                    case .success:
                        print("DataStore started")
                        continuation.resume(returning: true)
                    case .failure(let error):
                        print("Error starting DataStore:\(error)")
                        continuation.resume(throwing: error)
                    }
                }
            case .failure(let error):
                print("Error stopping DataStore:\(error)")
                continuation.resume(throwing: error)
            }
        }
    }
}

这是我尝试做的事情,但我遇到了上面提到的错误:

private func syncDataStore() async throws {
    try await withUnsafeThrowingContinuation { continuation in
        Amplify.DataStore.stop { (result) in
            switch(result) {
            case .success:
                Amplify.DataStore.start { (result) in
                    switch(result) {
                    case .success:
                        print("DataStore started")
                        continuation.resume()
                    case .failure(let error):
                        print("Error starting DataStore:\(error)")
                        continuation.resume(throwing: error)
                    }
                }
            case .failure(let error):
                print("Error stopping DataStore:\(error)")
                continuation.resume(throwing: error)
            }
        }
    }
}

说实话,我不知道它为什么在抱怨,没有返回值,也没有与任何模型或其他东西绑定...

1
如果显式指定continuation的类型会发生什么?(continuation: UnsafeContinuation<Bool, Error>) in我期望错误会变得更有用,或者最好是完全消失。 - Sweeper
@Sweeper,它的写法是这样的:(continuation: UnsafeContinuation<Void, Error>) in,但是看起来太长了,有没有更好的方法? - ElKePoN
我认为根本原因是你放在闭包里的语句太复杂了,类型推断就放弃了。你可以尝试将 stopstart 分别封装成异步函数,然后编写一个异步函数来处理 syncDataStore 就会变得轻而易举。 - Sweeper
实际上,应该可以返回Void的异步函数。尝试将其更改为-> Void - Sweeper
@Sweeper,那个不起作用。 - ElKePoN
5个回答

7
关键在于将withUnsafeThrowingContinuation的返回值强制转换为Void,如下所示:
try await withUnsafeThrowingContinuation { continuation in
    someAsyncFunction() { error in
        if let error = error { continuation.resume(throwing: error) }
        else { continuation.resume() }
    }
} as Void

5

这是最好的方法:

try await withUnsafeThrowingContinuation { (continuation: UnsafeContinuation<Void, Error>) in

1

让我们看一下签名(signature)

/// Suspends the current task,
/// then calls the given closure with the an unsafe throwing continuation for the current task.
///
/// - Parameter fn: A closure that takes an `UnsafeContinuation` parameter.
/// You must resume the continuation exactly once.
///
/// - Returns: The value passed to the continuation by the closure.
///
/// If `resume(throwing:)` is called on the continuation,
/// this function throws that error.
@available(macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0, *)
public func withUnsafeThrowingContinuation<T>(_ fn: (UnsafeContinuation<T, Error>) -> Void) async throws -> T

正如所见,withUnsafeThrowingContinuation 是一个带有泛型返回值的函数,其类型是从 continuation 中检测出来的。

因此,您的情况的解决方案可以如下:

private func syncDataStore() async throws {
    _ = try await withUnsafeThrowingContinuation { continuation in

        // ...

        continuation.resume(returning: true)

        // ...
    }
}

实际上它仍然会提供相同的错误信息: 无法推断泛型参数 'T' - ElKePoN
然后它是在我无法复制的代码中。提供的代码快照经过测试,可以在Xcode 13 / iOS 15上编译。 - Asperi
这段代码实际上返回一个 Bool,看一下 returning: true。它能工作,但并没有回答如何返回 Void 的问题。 - vicegax

0

在你的 "private func syncDataStore() async throws {...}" 中尝试这个:

return try await withUnsafeThrowingContinuation {....}

-1
private func syncDataStore() async throws -> Void {
    try await withCheckedThrowingContinuation { continuation in
        ...
        case .success:
            continuation.resume()
        case .failure(let error):
            continuation.resume(throwing: error)
        ...
    }
}

这在iOS 14上可以工作


你的回答可以通过提供更多支持信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便他人可以确认你的答案是正确的。您可以在帮助中心中找到有关如何编写良好答案的更多信息。 - Community

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接