ReactKit / SwiftState

Elegant state machine for Swift.
MIT License
904 stars 93 forks source link

Can't use event handler by itself #28

Closed joslinm closed 9 years ago

joslinm commented 9 years ago

Why can't I use the event handler by itself without adding a route? Shouldn't this be a design decision up to the client programmer?

machine.addEventHandler(.GotoPreviousCard, handler: { (event, transition, order, userInfo) -> Void in
  println("FeedView ! GotoPreviousCard")
})

Instead, I have to add a route that messes everything up. Sure, I can make it work but it's pretty pointless when I don't want to change states and instead I have code firing twice I would rather not be.

I would like my view to react to events without making state changes. If anything, I would rather filter events for certain states. For example, if someone "likes" a picture, you might send a Like event during the ShowingPhoto state. Your library could make the validation and what not.

In lieu of this functionality, I made transitions with nil => nil

inamiy commented 9 years ago

Hi, thanks for feedback :)

Actually, adding routes and handlers are totally different concepts. You should register all routes first to characterize the StateMachine's transition flow before adding any side-effects i.e. handlers. So, it is meaningless to just add handlers without declaring what routes are available.

In your case, if you want to invoke an "event handler" by .SomeEvent from any states without changing current one, you can add a route that is only available for .SomeEvent:

// add route for "anywhere to anywhere" but only valid when `.SomeEvent` is called
machine.addRouteEvent(.SomeEvent, transitions: [ nil => nil ])

// or, attach eventHandler all together
machine.addRouteEvent(.SomeEvent, transitions: [ nil => nil ], handler: { ... } )

Important thing here is: Adding routes are more important. Handlers are secondary.

(Also, please also note that you can't attach route by addHandler()/addEventHandler() although you can attach handler in addRoute()/addEventRoute())

inamiy commented 9 years ago

Ah, sorry. There seems to have a bug when I do the above (finished state will be .AnyState). I will fix this soon.

joslinm commented 9 years ago

Great, thanks! Let me know if I can help.

And thank you for your feedback. Actually, I use a state machine paradigm for just states and would enjoy the idea of passing events to states -- e.g., machine.addEventHandler(.SomeState, { ... } ).

The state for me is a greater view idea than a button being on / off do you know what I mean? It's in a Loading state or a Showing state or a Searching state etc.. I certainly don't overload the view controller here, but instead employ the VIPER pattern across these major components. I employ a state machine paradigm at the V or view level, whereas the P or presenter is the main director of the view. The view is dumb and merely just moves things around in response to state changes OR events. This makes communication between P and V well-defined with clear-cut split responsibilities.

inamiy commented 9 years ago

My above mentioned is fixed in #29. Please check StateMachineEventTests.swift#L89-L112 for more information.

inamiy commented 9 years ago

https://github.com/ReactKit/SwiftState/issues/28#issuecomment-119048410

Maybe you are only interested in current state and not transition. But actually, you can create the stay-still route i.e. .SomeState => .SomeState and attach handlers to it.

Also, Event is used for grouping state transitons, so it's good idea not to mix with State.

joslinm commented 9 years ago

Hmm.. I'm not sure what you mean by grouping state transitions. My idea stems from seeing states as templates. These templates can have activity spawned on them via events. Take for example a simple photo editor in which you have an ADD TEXT state. From within that state, you can change fonts by sending events VC ! ("CHANGE_FONT", fontToChangeTo). I'm not too sure what your alternative is? Sure, I can send the same state with some new refresh data embedded within userInfo, but that's not as clean as sending events tightly coupled with their corresponding data.

inamiy commented 9 years ago

Sorry, I couldn't understand your question... Is your above question related to the first one?

joslinm commented 9 years ago

Code looks good. I'm just explaining my paradigm and how your library fits into it. Let me know if you have any questions. Thanks again.

inamiy commented 9 years ago

All right. You can create a new issue and explain your idea a bit more detailed, for example, using StateMachine diagram like https://en.wikipedia.org/wiki/Finite-state_machine.

Anyway! Thanks for your feedback :blush: