Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Proposal]: Expand "with(latestFrom .." with better (more convenient) implementation #204

Open
killev opened this issue Dec 7, 2018 · 0 comments

Comments

@killev
Copy link

killev commented Dec 7, 2018

It often happens when you need to inject a different kind of data as payload into signal chaining. Use cases:

1. Pass state on button tap:

let state = Property("Some payload")
let button = UIButton()
button.reactive.tap.map { state.value }.bind(to: ...)//Bind it to somewhere we need Signal<Data>

2. Pass object (usually it's self) as weak/unowned on button tap:

unowned

let button = UIButton()
button.reactive.tap.observeNext {[unowned self] in 
self.doSomething() //it's dangerous, as it can already be dead as we don't increase ARC counter :(
self.doSomething() 
}

weak

let button = UIButton()
button.reactive.tap.observeNext {[weak self] in 
  guard s = self else { return } // Using weak - we have to write this "guard" everywhere :(
  s.doSomething() //but it's safe at least
  s.doSomething()
}

3. Pass strong reference to simple object constant

let data = "Some payload"
let button = UIButton()
button.reactive.tap.map { data }.bind(to: ...) //Bind it to somewhere we need Signal<Data>

4. Pass latest data from signal:

let state = Property("Some payload").map { $0.length }
let button = UIButton()
button.reactive.tap.with(latestFrom: state).bind(to: ...)//Bind it to somewhere we need Signal<Data>

For the 1st and the last cases we can use with(latestFrom. The issues are:

  • 2,3 cases are not covered.
  • It's hard to combine several payloads into one signal with(latestFrom:, combine: ).with(latestFrom:, combine: ).with(latestFrom:, combine:) demands providing more and more complicated function for tuple destructing (combine). And you need to write twice more code.

On my own project, I've implemented the function with like in this gist: https://gist.github.com/killev/6ea48dc8fdfd661472d50af42e4f9df2

so that it's possible to use it like below:

send.with(.weak(cousin), .weak(traveler), .val(content))

 sayThanks.with(.latest(model.reactive.cousin),
                        .latest(ApplicationService.instance.travelerAccount.ignoreNil()),
                        .strong(.thanks))
            .bind(to: Router.showMessageComposerS).dispose(in: reactive.bag)

It has declares .latest, .val, .weak, .strong to be used for defenter use cases.

PS. I really stand for different implementation for .val and .latest as .latest keeps a strong reference to the latest payload, what causes side effects. .val - keeps a reference to Property instead. In general - they're equal, however.

@killev killev changed the title [Proposal]: Expand "with(latestFrom .." with better [Proposal]: Expand "with(latestFrom .." with better (more convenient) implementation Dec 7, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant