Search code examples
iosswiftversioncombine

Swift Combine and iOS version limitations?


For example AppTrackingTransparency exists in iOS 14+ but an app supports iOS 13+.

I used the following code:

@available(iOS 14, *)
    func requestATTPermissions() ->
    Future<ATTrackingManager.AuthorizationStatus, Never> {
    ...
}

if #available(iOS 14, *) {
            requestATTPermissions()
                .sink { [weak self] _ in
                    self?.completion?()
                }
                .store(in: &combineSubscriptionCollector.subscriptions)
        } else {
            completion?()
        }

But is it possible to move if #available(iOS 14, *) { into Future/AnyPublisher which in iOS 13 works like Just(()) and in iOS14+ requests ATT? Somehow like this:

Just(()).map {
  if #available(iOS 14, *) {
    return requestATTPermissions()
       .map { status in ... }
  } else {
    return Just(())
  }
}
.sink { [weak self] _ in
    self?.completion?()
}
.store(in: &combineSubscriptionCollector.subscriptions)

Solution

  • If I understand correctly, you just need to use flatMap instead of map:

    Just(()).flatMap { _ in
        if #available(iOS 14, *) {
            return requestATTPermisions().map { status in
                // do not return anything here...
            }.eraseToAnyPublisher()
        } else {
            return Just(()).eraseToAnyPublisher()
        }
    }
    // .sink and .store...
    

    Though I think this is easier to read and understand:

    let publisher: AnyPublisher<(), Never>
    if #available(iOS 14, *) {
        publisher = requestATTPermisions().map { status in
            // ...
        }.eraseToAnyPublisher()
    } else {
        publisher = Just(()).eraseToAnyPublisher()
    }
    publisher.sink { ... }.store(in: ...)