Combine delay & switchToLatest publisher don't emit value sometimes

Hello,

I recently implemented a conditional debounce publisher using Swift's Combine.

If a string with a length less than 2 is passed, the event is sent downstream immediately without delay. If a string with a length of 2 or more is passed, the event is emitted downstream with a 0.2-second delay.

While writing test logic related to this, I noticed a strange phenomenon: sometimes the publisher, which should emit events with a 0.2-second delay, does not emit an event.

The test code below should have all indices from 1 to 100 in the array, but sometimes some indices are missing, causing the assertion to fail. Even after observing completion, cancel, and output events through handleEvents, I couldn't find any cause. Am I using Combine incorrectly, or is there a bug in Combine?

I would appreciate it if you could let me know.

import Foundation
import Combine

var cancellables: Set<AnyCancellable> = []

@MainActor func text(index: Int, completion: @escaping () -> Void) {
    let subject = PassthroughSubject<String, Never>()
    let textToSent = "textToSent"
    subject
        .map { text in
            if text.count >= 2 {
                return Just<String>(text)
                    .delay(for: .seconds(0.2), scheduler: RunLoop.main)
                    .eraseToAnyPublisher()
            } else {
                return Just<String>(text)
                    .eraseToAnyPublisher()
            }
        }
        .switchToLatest()
        .sink {
            if $0.count >= 2 {
                completion()
            }
        }.store(in: &cancellables)

    for i in 0..<textToSent.count {
        let stringIndex = textToSent.index(textToSent.startIndex, offsetBy: i)
        let stringToSent = String(textToSent[textToSent.startIndex...stringIndex])
        subject.send(stringToSent)
    }
}

var array = [Int]()

for i in 1...100 {
    text(index: i) {
        array.append(i)
    }
}

DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
    for i in 1...100 {
        assert(array.contains(i))
    }
}

RunLoop.main.run(until: .now + 10)
Combine delay &amp; switchToLatest publisher don't emit value sometimes
 
 
Q