pointfreeco / swift-composable-architecture

A library for building applications in a consistent and understandable way, with composition, testing, and ergonomics in mind.
https://www.pointfree.co/collections/composable-architecture
MIT License
11.93k stars 1.38k forks source link

More than five views in SwitchStore #602

Closed falcowinkler closed 3 years ago

falcowinkler commented 3 years ago

The new SwitchStore supports a maximum of 5 views

     SwitchStore(self.store) {
            CaseLet(state: /ContentViewState.someView,
                    action: ContentViewActions.someViewAction,
                    then: SomeView.init)
            CaseLet(state: /ContentViewState.someView,
                    action: ContentViewActions.someViewAction,
                    then: SomeView.init)
            CaseLet(state: /ContentViewState.someView,
                    action: ContentViewActions.someViewAction,
                    then: SomeView.init)
            CaseLet(state: /ContentViewState.someView,
                    action: ContentViewActions.someViewAction,
                    then: SomeView.init)
            CaseLet(state: /ContentViewState.someView,
                    action: ContentViewActions.someViewAction,
                    then: SomeView.init)
            // Five different views are fine.
            // Another view: Compiler error
            // CaseLet(state: /ContentViewState.someView,
            //        action: ContentViewActions.someViewAction,
            //        then: SomeView.init)
        }

because there are just five function overloads for the different number of views.

I am wondering if there's an elegant way to add more than five views, other than defining another initializer extension. Using seperate SwitchStore statements doesn't work, because i get a giant red debug warning that a case occured in the other SwitchStore that is not accomodated.

lukeredpath commented 3 years ago

There's no solution to this besides adding extra overloads.

I wonder why they are currently capped at 5 - in theory it should be able to support up to 10 (which is the maximum number of child views that can be added to a SwiftUI view).

Of course there is still going to be a hard limit in this case. I would expect enum state with more than 10 cases to be exceptional. 10 should be plenty for both use cases.

If you needed more then I can think of two workarounds. One is to just skip SwitchStore and use IfLetStore directly. You can use a Group to work around the maximum child view limitation.

The second would be to group your enum cases into separate enums and nest them into a new wrapper enum with a case for each sub group. This is a similar hierarchy to the above solution but implemented in your state instead of your view. It would allow you to use multiple SwitchStore views but it's a bit artificial and it's a bit gross.

falcowinkler commented 3 years ago

Allright, thanks a lot for the insights. By the way: I'm working on a learning app that displays different challenges on one screen, where the enum state fit's perfect. In this case, it's not so absurd to have > 10 kinds of challenges. Fortunately it's only 6 until now.

mbrandonw commented 3 years ago

Hey @falcowinkler, we'll play around with the impact of adding 10 overloads. We were worried about compile times, but never actually tested it.

In the meantime you can also use multiple SwitchStores with a Default case to get around the exhaustivity checking:

SwitchStore(self.store) {
  CaseLet(...)
  CaseLet(...)
  CaseLet(...)
  CaseLet(...)
  CaseLet(...)
  Default { }
}
SwitchStore(self.store) {
  CaseLet(...)
  CaseLet(...)
  CaseLet(...)
  CaseLet(...)
  CaseLet(...)
  Default { }
}

It's a hack, but hopefully we can add more overloads.