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

[WIP] User Interface Recipes #2660

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open

Conversation

liscio
Copy link
Contributor

@liscio liscio commented Jan 13, 2016

Please note that this document is very much a work in progress. Some things that I've left to do:

  • Remove the dependency on https://github.com/neilpa/Rex
  • Produce an actual example project. (Much of the below code was typed "raw" into my text editor, and likely won't compile.)
  • Get feedback from people who have been doing this much longer
  • Fix the TODOs

There really isn't any sort of "canonical document" for creating UI code using ReactiveCocoa, and that's probably due to the fact that it's difficult to find a single approach or "recipe" that applies to all scenarios. In my own work on Capo and FuzzMeasure over the past 6 months I have found so many different scenarios and examples that forced me to repeatedly question what I was doing.

Just when I think that I have an approach figured out, I find another handful of new challenges when I move to another part of the UI to work on. For instance, when I built a lot of iOS UI code I found that it was very easy to build static UIs for UITableViewCells and use ViewModels to ensure that I encapsulate the presentation behavior.

Once I moved to editable controls for the Neptune UI I faced a whole new set of challenges when trying to get values propagated from my ViewModel down into my audio engine, and encapsulating a live-updating visualization (that wasn't needlessly updating the screen while playback wasn't active, also!)

I feel that this collection of "Recipes" for various UI patterns would be extremely helpful to people that are new to ReactiveCocoa, and folks that might be looking for ideas when discovering new challenges that they haven't faced before.

Please note that this document is *very much* a work in progress. Some things that I've left to do:

- [ ] Remove the dependency on https://github.com/neilpa/Rex
- [ ] Produce an actual example project. (Much of the below code was typed "raw" into my text editor, and likely won't compile.)
- [ ] Get feedback from people who have been doing this much longer
- [ ] Fix the TODOs

## Motivation / Author Notes (To remove for final docs, if deemed inappropriate.)

@liscio - Jan 2016

There really isn't any sort of "canonical document" for creating UI code using ReactiveCocoa, and that's probably due to the fact that it's difficult to find a single approach or "recipe" that applies to all scenarios. In my own work on [Capo](http://capoapp.com) and [FuzzMeasure](http://fuzzmeasure.com) over the past 6 months I have found so many different scenarios and examples that forced me to repeatedly question what I was doing. 

Just when I think that I have an approach figured out, I find another handful of new challenges when I move to another part of the UI to work on. For instance, when I built a lot of iOS UI code I found that it was very easy to build static UIs for `UITableViewCell`s and use `ViewModel`s to ensure that I encapsulate the presentation behavior.

Once I moved to editable controls for the [Neptune](http://capoapp.com/neptune) UI I faced a whole new set of challenges when trying to get values propagated from my ViewModel down into my audio engine, and encapsulating a live-updating visualization (that wasn't needlessly updating the screen while playback wasn't active, also!)

I feel that this collection of "Recipes" for various UI patterns would be extremely helpful to people that are new to ReactiveCocoa, and folks that might be looking for ideas when discovering new challenges that they haven't faced before.
For example, consider a UI that displays both a slider and a text field that represent a magnitude. The text field specifies its values in dBFS (decibels, full scale). A common approach is to expose these values in your ViewModel using only a single `MutableProperty`:

``` swift
final class VolumeViewModel {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not keen at all on the word "view model". The term is overloaded and it has too much baggage.
To avoid confusion, how about just VolumeData, or if you want, VolumeViewData?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, I dislike the term as well.

I've switched to ViewData as the default naming for much of my own code and have even kicked around the use of Presenter in some spots. I only used ViewModel due to its recognition from other frameworks and the "MVVM Craze" though I suppose that will die down over time.

(The joys of a one-man coding team—schizophrenic/inconsistent naming conventions!)

I tend to agree with the overall sentiment from this article so I'd be glad to help spread a better approach to figuring this all out.

Any war stories you and others can share in terms of usage/architecture will be helpful.

@NachoSoto
Copy link
Member

Awesome idea! 😍 Thanks for getting this started. I'll take a closer look in a few days :)

Also tweaked other text as well.
@RuiAAPeres
Copy link
Member

This looks really nice @liscio. ❤️ I also started this.

@@ -0,0 +1,136 @@
# User Interface Recipes

### ViewData (aka ViewModel, Presenter) Objects
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should default to ViewModel here since that's been the preferred RAC terminology. (See also: https://github.com/ReactiveCocoa/ReactiveViewModel)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It sounds like there's a ViewData vs ViewModel (and Presenter) discussion that needs to be resolved at some point.

And is that ReactiveViewModel repo even considered useful anymore? Especially considering that the Objective-C API will be disappearing soon in the RAC 5 release?

@mdiep
Copy link
Contributor

mdiep commented May 6, 2016

@liscio Is this something you're still interested in pursuing?

@liscio
Copy link
Contributor Author

liscio commented May 6, 2016

@mdiep Certainly, as time permits.

Thanks for all the feedback & suggestions so far!

@liscio
Copy link
Contributor Author

liscio commented Jun 24, 2016

Sorry this has sat stale for so long. There are a few things that are holding it up:

  1. https://github.com/neilpa/Rex being merged into the RAC organization. This will make it easier to pick up some of the UI bits and pieces that Rex exposes. Of course this doesn't stop me from writing about the approach, but it probably shouldn't be merged until that happens.
  2. My open PR in Rex with "bindings" code for UI work. As I was writing the documentation above I was in the middle of coding another project that used a different approach than what I describe here. I don't want to jump the gun and prescribe anything approaching a "right way" to build UI until I feel confident that I have an approach that works. :)

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

Successfully merging this pull request may close these issues.

None yet

4 participants