ScottRobbins / DeclarativeLayout

A declarative, expressive and efficient way to lay out your views.
MIT License
5 stars 0 forks source link

Musings on how to make it easier to control the flow of data for updating your UI #39

Open ScottRobbins opened 5 years ago

ScottRobbins commented 5 years ago

originally brought up in https://github.com/HotCocoaTouch/DeclarativeLayout/issues/31

I also think this wrapper should think much harder about how to handle data to make updating state and having that trigger updates to the view easy.

ScottRobbins commented 5 years ago

Ignoring settings colors and non views/constraints, one possible direction is to build if statements into the layout:

ViewLayout(view: self.view) { (com) in
    com.stackView { (com) in 
        com.if(/*some condition*/) { (com) in 
            com.arrangedView(self.myView) { (com) in 
                ...
            }
        }.elseif(/*some condition*/) { (com) in 
            ...
        }.else(/*some condition*/) { (com) in
            ...
        }
    }
}

One part of this is that you'd no longer be explicitly calling to update your layout. You're describing it here. This function that describes the layout gets executed once.

So how could this work?

The condition statements inside of the if() function could require what is passed in to be a function. Something that we can store and later re-evaluate. Ideally these functions would be pure.

One of the tricks already to this framework is that at the call site, no constraints have been activated and no constraints. It also stores all of the decisions about view hierarchy and constraints in a tree of components.

The if statements would mark components under it to be active or inactive. This could be used to get the active constraints and current view layout that could be re-run through the diffing algorithm.


The next thing to solve is how to know when to re-evaluate the layout to make adjustments. The simplest implementation of this is to have each view layout store a single "ViewState" or "ViewModel" object. Require that for this framework to work, the functions inside of if() functions use data from only the view model. When the view layout's view state changes, it can re-run the decision functions to find what components should be active and automatically update things.

ScottRobbins commented 5 years ago

What I see as the pros of this:

ScottRobbins commented 5 years ago

Some cons:

ScottRobbins commented 5 years ago

There are also a couple concerns:

ScottRobbins commented 5 years ago

to handle the other UI stuff, we can probably make some kind of bindings interface: https://www.swiftbysundell.com/posts/bindable-values-in-swift

This doesn't work for all UIKit things because a lot has to be done with closures because UIKit sometimes relies on method calls. But a closure API could be tacked onto that.

I think this would work really well for UI configuration, but can it also work for deciding what path to go down for constraints/subviews being on screen? It's similar to the .if() I had there.

ScottRobbins commented 5 years ago

I think that if I go down this route I should remove the component returns from the APIs. The library will have strong enough opinions that making an opinionated library around it won't be easily possible.

ScottRobbins commented 5 years ago

There are also going to be times when you want to bind on multiple properties on a view state and we can't really do variadic generics in that way so you'd need some other type of API.

ScottRobbins commented 5 years ago

I think that going with a purely functional approach as I mocked up elsewhere with enums/structs, and using something like .if(