My main problem is that I'm trying to work around the (undocumented) fact that @Published
properties don't update the property's value until after subscribers have been notified of the change. I can't seem to get a good way around it.
Consider the following contrived combination of a Subject
and @Published
properties. First, a simple class:
class StringPager {
@Published var page = 1
@Published var string = ""
}
let pager = StringPager()
And then a simple passthrough subject:
let stringSubject = PassthroughSubject<String, Never>()
For debugging, let's subscribe to the string property and print it out:
pager.$string.sink { print($0) }
So far so good. Next, let's subscribe to the subject and alter the pager based on its value:
stringSubject.sink { string in
if pager.page == 1 {
pager.string = string
} else {
pager.string = string.uppercased()
}
}
Hopefully, this logic will allow us to make the pager string uppercased whenever we're not on the first page.
Now let's send values through the stringSubject when the page gets updated:
pager.$page.sink {
$0 == 1 ? stringSubject.send("lowercase") : stringSubject.send("uppercase")
}
If we've gotten this logic right, then lowercase will always be lowercased, while uppercase will always be uppercased. Unfortunately, that's not at all what happens. Here's a sample output:
pager.page = 1 // lowercase
pager.page = 2 // uppercase
pager.page = 3 // UPPERCASE
pager.page = 4 // UPPERCASE
pager.page = 1 // LOWERCASE
pager.page = 1 // lowercase
The reason for this is when we subscribe to the subject, we check the value of pager.page
... but updating pager.page
is what triggers the subject's closure, so the pager.page
doesn't have an updated value yet, so the subject executes the wrong branch.
I've tried fixing this by both zip
ing the pager.$page
with the subject before sinking:
stringSubject.zip(pager.$page).eraseToAnyPublisher().sink { ...same code... }
as well as combineLatest
ing it:
stringSubject.combineLatest(pager.$page).eraseToAnyPublisher().sink { ...same code... }
but that leads either to the exact same observed behavior (in the former case) or equally undesired behavior except more of it (in the latter case).
How can I get the current page within the subject sink
closure?