Visualize Combine Magic with SwiftUI — Part 4
What are the differences between Zip and CombineLatest
In the previous chapter, we successfully built a playground that accommodates operators like merge
and append
who take a list of Publishers and produce new one with the same type. Today, we want to crank it up a notch. We want to visualize operators that produce a tuple of all types of the Publishers. Both zip
and combineLatest
share this kind of behavior. Given 2 Publishers of String type, they will produce a new Publisher of<(String,String)>
. In the end of this chapter, we will be able to tell the differences between zip
and combineLatest
by simply looking at the playground.
Add a wrapper around CircularView
In order to visualize tuples of values that are emitted from the operators, we concatenate CircularTextView to represent a tuple.
MultiCircularText is a wrapper of CircularTextView with an array of Strings.
@Binding var streamValues: [[String]]
TunnelView now holds 2-dimensional values.
ForEach(streamValues.reversed(), id: \.self) { texts in
MultiCircularTextView(texts: texts)
}
Everything stays the same except we use MultiCircularTextView and pass in this 2-dimensional texts.
struct TunnelView_Previews: PreviewProvider {static var previews: some View {
Section {
TunnelView(streamValues: .constant([["1"], ["2"], ["3"]]))
TunnelView(streamValues: .constant([["A"], ["B"], ["C"]]))
TunnelView(streamValues: .constant([["1", "A"], ["2", "B"], ["3", "C"]]))
}.previewLayout(.sizeThatFits)
}
}
Let’s preview quickly.
There you go. We can visualize tuple type now.
Upgrade single dimensional StreamView into 2-dimensional
@State private var stream1Values: [[String]] = []@State private var stream2Values: [[String]] = []@State private var streamResultValues: [[String]] = []var comparingPublisher: (AnyPublisher<String, Never>, AnyPublisher<String, Never>) -> (AnyPublisher<(String, String), Never>)
As you can see, all the stream values are 2-dimensional array now. Additionally, you can see the result of comparingPublisher closure is now a Publisher of Sting tuple.
Give it up to Zip and CombineLatest
Now we have prepared our playground. Let’s send Publishers operated by zip
and combineLatest
into DoublePublisherStreamView.
let publisher = self.invervalValuePublisher(array: ["1", "2", "3", "4"], interval: 1)let publisher2 = self.invervalValuePublisher(array: ["A", "B", "C", "D"], interval: 1.5)
Notice we delay publisher2’s value emission to make the result stand out between zip
and combineLatest
.
Here is the final result.
Because of the long width of the combined result, we display the playground in landscape.
Now you can easily tell that
Zip waits until both publishers emit values before it does while CombineLatest emits value whenever one of the sources does and combine its result with the latest values from other publishers.
Link to Source Code
Next chapter: Refine the playground
As we mentioned in chapter1, there are a few issues we found in this playground.
- The values in stream are sorted by the “String” value, not by emitted time.
- CircularView appears out of nowhere instead of appearing and moving from the entrance of the “tunnel” toward the front of the queue.
- In this chapter, we also notice that this tunnel only displays a limit amount of CircularView. When there are too many views in the tunnel, we want to move older views “out” toward the right side of the screen to keep space available for new views.
Since this is a series of both Combine and SwiftUI, in the next chapter, we will spend some time on SwiftUI components. Hopefully, all the streams will look better and more intuitive in terms of Combine’s visualization.
See next chapter, series Part 5 – SwiftUI ViewModifier, Animation, and Transition
There are certainly more I can learn than share. Please drop a line if you resonate or disagree with anything you see here.