lolgear
(Dmitry Lobanov)
1
Consider following Service that captures data.
class Service {
var captured: String = ""
func save(_ captured: String) -> String {
self.captured = data
return captured
}
func myPublisher() -> AnyPublisher<String, Error> {
// ... configure publisher ...
return publisher.map(self.save)
}
}
Example above doesn't work, because it causes memory leak if I understand map() correctly.
Could we add .alongside publisher which captures [weak self] and behaves exactly as map which captures non-escaping closure:
// kind of..
func alongside<Value, P: Publisher>(value: Value, block: (Value) -> Void) -> P {
block(value) // waiting
return value
}
OR
We could add publisher that accepts functions instead like assign:
.alongside(\.save, on: self)
xwu
(Xiaodi Wu)
2
Combine is not a part of the open-source Swift project and is not therefore within the scope of the Swift Evolution process. I think there may be ways to offer suggestions to Apple.
2 Likes
mayoff
(Rob Mayoff)
3
I don't see any memory leak in your example. You return a publisher that retains the Service, but you didn't include any code that makes the Service retain the publisher.
1 Like
lolgear
(Dmitry Lobanov)
4
Interesting point. Maybe I should rethink current Service model.
However, in outer code it would be used as:
class ViewModel {
private var service: Service = .init()
var subscription: AnyCancellable?
func setup() {
self.subscription = self.service.myPublisher().sink{ (value) in
// process value from publisher.
}
}
}
mayoff
(Rob Mayoff)
5
You probably need to use [weak self] in the “process value from publisher” closure, if you use self in that closure.
lolgear
(Dmitry Lobanov)
6
Do you mean that everything is fine in this example, because view model retains service and also publisher retains service?
But it seems a bit weird, because publisher can't retain service, no?
lolgear
(Dmitry Lobanov)
8
Because Service produces publisher...
Maybe I don't understand common patterns with Combine / Reactive.
So, this implementation allows following tricky code:
// We don't bother about lifetime of service.
// Service's publisher retains service.
self.subscription = Service.init().myPublisher().sink{
[weak self] (value) in
self?.update(newValue: value)
}