Need help with StateMachine?
Click the “chat” button below for chat support from the developer who created it, or find similar developers for support.

About the developer

207 Stars 28 Forks MIT License 37 Commits 0 Opened issues


State machine library for Objective-C

Services available


Need anything else?

Contributors list

# 101,902
32 commits


State machine library for Objective-C

This library was inspired by the Ruby gem state_machine.


  • DSL for defining the state machine of your classes
  • Dynamically added methods to trigger events in the instances of your classes
  • Methods to query if an object is in a certain state (isActive, isPending, etc)
  • Methods to query wheter an event will trigger a valid transition or not (canActive, canSuspend, etc)
  • Transition callbacks. Execute arbitrary code before and after a transition occurs.


As a CocoaPod

Just add this to your Podfile

pod 'StateMachine', '~> 0.1'

Other approaches

  • You should be able to add StateMachine to you source tree. If you are using git, consider using a
    git submodule


Defining the state machine of a class

Let's model a Subscription class

At this moment you are responsible of defining a state property like this. In the future this will be handle by StateMachine

@interface Subscription : NSObject
@property (nonatomic, retain) NSString *state; // Property managed by StateMachine

@property (nonatomic, retain) NSDate *terminatedAt;

  • (void) stopBilling; @end

Here is the fun part. In the implementation of the class we use the StateMachine DSL to define the valid states and events. For each event you define which are the valid transitions.

The DSL is a work in progress and will change

You also have to include a call to

in you constructor(s) for the moment. The goal is to remove this limitation and be less intrusive.
@implementation Subscription

STATE_MACHINE(^(LSStateMachine *sm) { sm.initialState = @"pending";

[sm addState:@"pending"];
[sm addState:@"active"];
[sm addState:@"suspended"];
[sm addState:@"terminated"];

[sm when:@"activate" transitionFrom:@"pending" to:@"active"];
[sm when:@"suspend" transitionFrom:@"active" to:@"suspended"];
[sm when:@"unsuspend" transitionFrom:@"suspended" to:@"active"];
[sm when:@"terminate" transitionFrom:@"active" to:@"terminated"];
[sm when:@"terminate" transitionFrom:@"suspended" to:@"terminated"];

[sm before:@"terminate" do:^(Subscription *subscription){
    subscription.terminatedAt = [NSDate dateWithTimeIntervalSince1970:123123123];

[sm after:@"suspend" do:^(Subscription *subscription) {
    [subscription stopBilling];


  • (id)init { self = [super init]; if (self) {

      [self initializeStateMachine];

    } return self; }

  • (void) stopBilling { // Yeah, sure... }


StateMachine will methods to your class to trigger events. In order to make the compiler happy you need to tell it that this methods will be there at runtime. You can achieve this by defining the header of an Objective-C category with one method per event (returning BOOL) and the method

. Just like this:
@interface Subscription (State)
- (void)initializeStateMachine;
- (BOOL)activate;
- (BOOL)suspend;
- (BOOL)unsuspend;
- (BOOL)terminate;

  • (BOOL)isPending;

  • (BOOL)isActive;

  • (BOOL)isSuspended;

  • (BOOL)isTerminated;

  • (BOOL)canActivate;

  • (BOOL)canSuspend;

  • (BOOL)canUnsuspend;

  • (BOOL)canTerminate; @end

As you can see, StateMachine will define query methods to check if the object is in a certain state (isPending, isActive, etc) and to check whether an event will trigger a valid transition (canActivate, canSuspend, etc).

Triggering events

Now you can create instances of your class as you would normally do

Subscription *subscription = [[Subscription alloc] init];

It has an initialState of

subscription.state; // @"pending"

You can trigger events ```objc [subscription activate]; // retuns YES because it's a valid transition subscription.state; // @"active"

[subscription suspend]; // retuns YES because it's a valid transition // Method stopBilling was called subscription.state; // @"suspended"

[subscription terminate]; // retuns YES because it's a valid transition subscription.state; // @"terminated" subcription.terminatedAt; // [NSDate dateWithTimeIntervalSince1970:123123123]; ```

If we trigger an invalid event

// The subscription is now suspended
[subscription activate]; // retuns NO because it's not a valid transition
subscription.state; // @"suspended"


  1. Fork it
  2. Create your feature branch
  3. Commit your changes
  4. Push to the branch
  5. Create new Pull Request

We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.