Weak assignment in Combine
08 Apr 2020 ⇐ Notes archive(This is an entry in my technical notebook. There will likely be typos, mistakes, or wider logical leaps — the intent here is to “let others look over my shoulder while I figure things out.”)
Publisher.assign(to:on:) comes with a pretty big warning label,
The
Subscribers.Assigninstance created by this operator maintains a strong reference toobject[…]
and we need to read this label when piping publishers to @Published properties in ObservableObject conformances.
Of course, we could do the sink-weak-self-receiveValue dance. But, that’s a bit of ceremony.
My first instinct was to weak-ly overload assign and PR’d it to CombineExt, in case it’d help others, too. And with some distance and thoughtful feedback from both Shai and Adam, I decided to re-think that instinct.
There’s a few downsides to Publisher.weaklyAssign(to:on).
- It crowds an already packed
Publishernamespace. - In its current form, it doesn’t relay which argument is
weakly captured. A clearer signature would be.assign(to:onWeak:)(and similarly, for anunownedvariant).
Adam mentioned a couple of alternatives:
-
“Promote” the
weakkeyword to a sort of function by way of aWeakBoxtype and assign onto it. I tried to make this work—learning more than I bargained for about dynamic member lookup along the way—and ran into a tradeoff dead end. -
Encode the weak capture semantics at the type level à la the
Bindingspackage. Which, felt a bit out of scope forCombineExt, since it’s more of an operator collection.
So, I’m back to where I started and with a slightly modified overload. Gist’ing it below for the curious.
Now call sites can read—
Ah! Almost forgot. Writing tests for the operator had me reaching for Swift.isKnownUniquelyReferenced(_:)—“a [free-function] I haven’t heard [from] in a long time, a long time.”