Я реализовал метод, который возвращает Future (издатель объединения), который выдает значение (или ошибку) из задачи, он работает в Swift 5:
func call(api: API) -> AnyPublisher<Data?, Error> {
return Future { promise in
Task {
let response = await AF.request( ... ).serializingData().response
if let error = response.error {
promise(.failure(error))
} else {
promise(.success(response.data))
}
}
}.eraseToAnyPublisher()
}
Приведенный выше код не удалось скомпилировать в Swift 6 со строгой проверкой параллелизма, поскольку promise
НЕ является отправляемым типом:
Capture of 'promise' with non-sendable type '(Result<Data?, any Error>) -> Void' in a `@Sendable` closure
Означает ли это, что в Swift 6 больше невозможно иметь издателя Объединения, который создает ценность асинхронным методом?
Я проверил документацию Apple Использование объединения для асинхронного кода вашего приложения, но в ней не упоминается, как смешивать «Объединить» и «Задачу» со строгой проверкой параллелизма.
Несвязано, но почему Data?
вообще необязательно? Цель типа Result
— возвращать необязательные типы как в success
, так и в failure
случаях. Кроме того, я согласен с Йоакимом, отказаться от Комбината в пользу async/await
.
Я понимаю, что лучше было бы переписать этот метод и принять его на вооружение async/await
. На данный момент я ищу промежуточное решение, чтобы мой проект мог использовать Swift 6 без переписывания большого количества кода.
Я считаю, что отсутствие аннотации @Sendable
на Future.Promise
является ошибкой, поскольку я считаю, что она должна быть потокобезопасной. Вы можете отправить отчет об отзыве в Apple.
На данный момент вы можете обойти это, используя синтаксис Swift 6 nonisolated(unsafe)
, чтобы компилятор не беспокоился об этом:
func call() -> AnyPublisher<Data?, Error> {
return Future { promise in
// Copy promise to a local property to make it nonisolated(unsafe):
nonisolated(unsafe) let promise = promise
Task {
// Now capture promise in a Sendable closure.
promise(.success(Data()))
}
}.eraseToAnyPublisher()
}
Зачем вам вообще нужно будущее, почему бы не переписать функцию, чтобы она использовала только async/await?