EthanLS
November 18, 2024, 9:29pm
1
AsyncSequence got changed in iOS 18, and now I can't figure out how to use it as a return type in a way that works with both 17 and 18.
Example:
func subscribe() -> any AsyncSequence<String> { ... }
Gives Error : Protocol type 'AsyncSequence' specialized with too few type arguments (got 1, but expected 2)
But this:
func subscribe() -> any AsyncSequence<String, Never> { ... }
Gives Error : 'Failure' is only available in iOS 18.0 or newer
Which I can fix by adding in @available(iOS 18.0, *)
-- but now I am back to having no iOS 17 API.
... I feel like there has to be an obvious, simple answer that I am just not seeing?
1 Like
vanvoorden
(Rick van Voorden)
November 18, 2024, 9:51pm
2
(I'm using Xcode 16 beta on macOS 14.5)
How do I get this to compile for both macOS 15 and macOS 14? :
public final class EmitterOfEvents {
public typealias Element = Int
public func notifications() -> some AsyncSequence<Element, Never> {
AsyncStream<Element>.makeStream().stream
}
}
I get error:
[Screenshot 2024-06-13 at 11.02.34]
I'm well aware of SE-0421 , and I'm excited about the change. Hopefully I'm just a bit tired right now and what I want is possible, but it feels like somethi…
There might be some ideas here that could help.
1 Like
joshw
(Josh)
December 15, 2024, 7:36am
3
Did you solve this? Or is it impossible to use AsyncSequence<SomeType>
as a return type for apps targeting below iOS 18?
No, sadly, the type erasure to any AsyncSequence
needs the PAT for Failure
introduced in iOS 18, macOS 15, etc.
For now, it’s easiest to use the concrete types, perhaps using typealias
to simplify its usage.
1 Like
vanvoorden
(Rick van Voorden)
December 16, 2024, 4:39am
5
This seems to compile from 6.0 and deploys (runs) on macOS 14.
public protocol EmitterProtocol<Element, Failure> {
associatedtype Element where Self.Sequence.Element == Element
@available(macOS 15.0, *) associatedtype Failure : Error = any Error where Self.Sequence.Failure == Failure
associatedtype Sequence : AsyncSequence
func notifications() -> Sequence
}
public final class Emitter : EmitterProtocol {
let (stream, continuation) = AsyncStream<Int>.makeStream()
public func no…
I'm still using this for a workaround. Instead of returning an opaque (or erased) AsyncSequence
… my idea here is to box a concrete AsyncSequence
in an opaque Container. The extra layer of indirection seems to help keep the compiler happy.
1 Like
EthanLS
December 19, 2024, 6:10pm
6
Nope.
It is impossible to use AsyncSequence<SomeType>
as a return type for code targeting support below iOS 18.
joshw
(Josh)
December 19, 2024, 6:34pm
7
So I guess this also means it's impossible to use a typed AsyncSequence as a return type in general pre ios 18?
You can use the concrete type of the sequence in question, you just lose type info if you make it opaque.
Already shared this with @joshw on Slack (we work together) but for visibility I thought I'd point out that swift-nio has a nice AnyAsyncSequence
type that can do the trick. Though folks have pointed out in the past that this can have sizable perf tradeoffs so probably best used sparingly.
self = .bufferedStream(iterator)
}
internal init(wrapping iterator: AnyAsyncSequence<Element>.AsyncIterator) {
self = .anyAsyncSequence(iterator)
}
}
}
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
internal struct AnyAsyncSequence<Element>: AsyncSequence {
private let _makeAsyncIterator: () -> AsyncIterator
internal init<S: AsyncSequence>(wrapping sequence: S) where S.Element == Element {
self._makeAsyncIterator = {
AsyncIterator(wrapping: sequence.makeAsyncIterator())
}
}
internal func makeAsyncIterator() -> AsyncIterator {
self._makeAsyncIterator()
1 Like