Reactive Programming in iOS with Combine

Feb 4 2021 · Swift 5.3, macOS 11.0, Xcode 12.2

Part 4: Timing, Scheduling and Sequencing Operators

26. Challenge: Collect Values by Time

Episode complete

Play next episode

Next
About this episode

Leave a rating/review

See forum comments
Cinema mode Mark complete Download course materials
Previous episode: 25. Timeout and measureInterval Next episode: 27. Scheduling Operators

Get immediate access to this and 4,000+ other videos and books.

Take your career further with a Kodeco Personal Plan. With unlimited access to over 40+ books and 4,000+ professional videos in a single subscription, it's simply the best investment you can make in your development career.

Learn more Already a subscriber? Sign in.

Transcript: 26. Challenge: Collect Values by Time

Open the starter challenge playground for this episode. You see some code waiting for you: a subject that emits integers and a function call that feeds the subject with mysterious data.

In between those parts, your challenge is to: group data by batches of 0.5 seconds. Turn the grouped data into a string. If there is a pause longer than 0.9 seconds in the feed, print the 👏 emoji. Hint: Create a second publisher for this step and merge it with the first publisher in your subscription.

Here’s another hint - if you want to convert an Int to a Character you do something like the code on screen.

Pause the video, try out a solution, and come back when you’re ready to see my solution.

Create a first publisher derived from the subject which emits the strings. Use collect() using the .byTime strategy to group data in 0.5 seconds batches. Map each integer value to a Unicode scalar, then to a character and then turn the whole lot into a string. Create a second publisher derived from the subject, which measures the intervals between each character.

If the interval is greater than 0.9 seconds, map the value to the 👏 emoji. Otherwise, map it to an empty string. The final publisher is a merge of both strings and the 👏 emoji. Filter out empty strings for better display. Print the result!

// 1
let strings = subject
  // 2
  .collect(.byTime(DispatchQueue.main, .seconds(0.5)))
  // 3
  .map { array in
    String(array.map { Character(Unicode.Scalar($0)!) })
  }

// 4
let spaces = subject.measureInterval(using: DispatchQueue.main)
  .map { interval in
    // 5
    interval > 0.9 ? "👏" : ""
  }

// 6
let subscription = strings
  .merge(with: spaces)
  // 7
  .filter { !$0.isEmpty }
  .sink {
    // 8
    print($0)
  }