Функция Async/Await без возврата | Свифт 5.5

avatar
ElKePoN
9 августа 2021 в 03:12
1288
4
6

Как я могу удалить возврат Bool из моей функции без получения ошибки:

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)
            }
        }
    }
}

Честно говоря, я не знаю, почему он жалуется, возвратов нет и он не привязан ни к какой модели или чему-то еще...

Источник
Sweeper
9 августа 2021 в 03:29
1

Что произойдет, если вы укажете тип continuation явно? (continuation: UnsafeContinuation<Bool, Error>) in Я ожидаю, что ошибка изменится на что-то более полезное, а лучше вообще исчезнет.

ElKePoN
9 августа 2021 в 03:36
0

@Sweeper это ушло так: (continuation: UnsafeContinuation<Void, Error>) in однако это выглядит слишком долго, разве нет лучшего способа?

Sweeper
9 августа 2021 в 03:42
0

Я думаю, основная причина в том, что операторы, которые вы помещаете в замыкание, слишком сложны, и вывод типа просто сдается. Вы можете попробовать обернуть stop и start в асинхронные функции отдельно, тогда написать асинхронную функцию для syncDataStore будет тривиально.

Sweeper
9 августа 2021 в 03:47
0

На самом деле асинхронные функции, возвращающие Void, должны быть возможны. Попробуйте изменить его на -> Void.

ElKePoN
9 августа 2021 в 04:03
0

@Sweeper, который не сработал

Ответы (4)

avatar
ElKePoN
11 августа 2021 в 00:01
4

Вот что сработало лучше всего:

try await withUnsafeThrowingContinuation { (continuation: UnsafeContinuation<Void, Error>) in
avatar
SirDeleck
25 января 2022 в 09:02
1

Хитрость заключается в том, чтобы преобразовать возвращаемое значение withUnsafeThrowingContinuation в Void, например:

try await withUnsafeThrowingContinuation { continuation in
    someAsyncFunction() { error in
        if let error = error { continuation.resume(throwing: error) }
        else { continuation.resume() }
    }
} as Void
avatar
Asperi
9 августа 2021 в 04:56
1

Давайте посмотрим на подпись

/// 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 это функция с дженериками по возвращаемому значению, тип которого определяется из продолжения

Итак, решение для вашего случая может быть следующим:

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

        // ...

        continuation.resume(returning: true)

        // ...
    }
}
ElKePoN
9 августа 2021 в 23:22
0

на самом деле это все еще выдает то же сообщение об ошибке: Generic parameter 'T' could not be inferred

Asperi
10 августа 2021 в 04:33
0

Тогда это код, который я не могу воспроизвести. Предоставленный снимок кода, как было протестировано, компилируется с Xcode 13/iOS 15.

avatar
workingdog support Ukraine
9 августа 2021 в 04:05
0

попробуйте это в вашем "приватном func syncDataStore() async throws {...}":

return try await withUnsafeThrowingContinuation {....}