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

Question: Should I do it the Redux style or not? #344

Open
ranhsd opened this issue May 8, 2018 · 6 comments
Open

Question: Should I do it the Redux style or not? #344

ranhsd opened this issue May 8, 2018 · 6 comments
Labels

Comments

@ranhsd
Copy link

ranhsd commented May 8, 2018

Hi,
I am working on a very big swift project and use ReSwift heavily in it. I always ask myself questions regarding: should I do it the redux style or not and I will explain:

In one of my screens I have a more options button which located on my navigation bar. When I press it the app present an action sheet (UIAlertController) to the user. The list of options which are available inside this action sheet are being calculated inside the reducer and my state contains an array of the list of more options (I use enum). I decided to it this way because this list can be changed according to the item status. So my state look like this:

struct ItemDetailState : StateType {
    ...
    var moreOptions : [ItemDetailsMoreOptions] // more options that can be taken on an item    
}

And when the user click on the more options button I build the UIAlertController dynamically from this list. Everything works as expected without any issues.
Now my indecision is what to do with presenting this action sheet. I have 2 options:

  1. When the user click on the more options button I simply present it inside my @IBAction function (the "classic way")
    @IBAction func onMoreOptionsItemButtonItemClicked(_ sender: UIBarButtonItem) {
        
        itemTransactionMapPopOver?.hide()
        
        presentMoreOptionsActionSheet()
    }
  1. The second option is to dispatch an action inside this function of PresentMoreOptionsActionSheet with the value of true or something like that and handle it inside the view controller newState listener
    func newState(state: ItemDetailsState) {
    
       .... 
        
        if state.displayMoreOptionsActionSheet {
            self.presentMoreOptionsActionSheet()
        }
    }
    @IBAction func onMoreOptionsItemButtonItemClicked(_ sender: UIBarButtonItem) {
        store.dispatch(ItemDetailsActions.SetDisplayMoreOptionsActionSheet(display: true))
    }

and in order to avoid presenting the action sheet multiple times inside the presentMoreOptionsActionSheet function I dispatch the same action but this time with the value of false so it will not be displayed again

store.dispatch(ItemDetailsActions.SetDisplayMoreOptionsActionSheet(display: false))

I would like to hear your thoughts about it? What do you think should I go with the redux style or not and this question is true for all other scenarios that I may face during the app development.

Thanks in advance.

@DivineDominion
Copy link
Contributor

Here's my 2 cents:

  • I don't see any benefit but lots of overhead with option (1)
  • iOS @IBAction handling is what the framework suggests, so it comes easiest (unless you rid yourself of most of UIKit, using functional view controllers or whatever), which is why I suggest starting with that
  • presentMoreOptionsActionSheet() sounds like a UI-internal concern: show the sheet. I don't see any benefit in putting this into the state unless you want to restore the view hierarchy from your state somehow
  • assuming presentMoreOptionsActionSheet() creates a MoreOptionsViewController or whatever, this object may subscribe itself to your store and obtain the option set from there, so you don't really exit the ReSwift flow in my point of view

@ranhsd
Copy link
Author

ranhsd commented May 8, 2018

Hi , thanks for your quick response.

Actually the presentMoreOptionsActionSheet() create a UIAlertViewController inside the same class and simply present and because it’s located in the same class it has access to the moreOptions enum array. Consider these facts what do you think I should do?

Thanks.

@Dimillian
Copy link

I want to add my 2 cents. I have a big debate internally between a redux aware UI State and pure UIKit UI management. At the moment I'm doing a bit of both, for shared UI and shared modal I do all of it though redux, like this:

struct UIState: StateType, Equatable {

    enum SelectedTab: Int {
        case feed, badges, explore, me, more
    }

    enum PresentedModal: Int {
        case none, login, compose, scan, stats, arkit, booklistEditor, safari, badgeWin, other
    }

    var selectedTab = SelectedTab.feed
    var presentedModal = PresentedModal.none
    var presentedModalRelativeTo: UIViewController?
    var modalHistory: [PresentedModal] = []
    var shouldCloseModal = false

    var urlToOpen: URL?

    var orientation: UIDeviceOrientation = UIDevice.current.orientation
}

UI actions look like that

class UIActions: BaseActions {
    struct SetSelectedTab: Action {
        let selectedTab: UIState.SelectedTab
    }

    struct PresentModal: Action {
        let modal: UIState.PresentedModal
        let relativeTo: UIViewController?
    }
}

And I have a main controller which listen to the UI State and present modal accordingly.

Of course, I can't do that for everything, but it helped quite a lot with modal stacking management and routing.

@ranhsd
Copy link
Author

ranhsd commented May 9, 2018

Hi @Dimillian thanks for your response.
I wanted to know where exactly you integrate this UIState? it's a sub state of the current view controller state that you run into?

Thanks.

@Dimillian
Copy link

Dimillian commented May 9, 2018

It's a substate of my AppState:

struct AppState: StateType, Equatable {
    var usersState: UsersState
    var booksState: BooksState
    ...
    var uiState: UIState
    ...
}

Then I can connect on it if I want to be specific

        store.subscribe(self) {
            $0.select { $0 }.skipRepeats({ (oldState, newState) -> Bool in
                oldState.uiState == newState.uiState
            })
        }

@ranhsd
Copy link
Author

ranhsd commented Oct 3, 2018

Hi @Dimillian I know that a lot of time pass since I your last response on this thread but I have only one questions about the Main View Controller that you mentioned above who's responsible to present the modals. The main view controller is the view controller which contains all the tabs of your app? If not where exactly you are initiate it?

Thanks.
Ran.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants