|
| 1 | + |
| 2 | + |
| 3 | +# Stately [](https://raw.githubusercontent.com/softwarenerd/Stately/master/LICENSE.md) [](https://github.com/softwarenerd/Stately/releases) [](https://travis-ci.org/softwarenerd/Stately) |
| 4 | + |
| 5 | +## Introduction |
| 6 | + |
| 7 | +[Stately](https://github.com/softwarenerd/Stately) is a pure Swift framework for iOS, macOS, watchOS, and tvOS that implements an event-driven finite-state machine. |
| 8 | + |
| 9 | +For information on finite-state machines, see the Wikipedia article [Finite-state machine](https://en.wikipedia.org/wiki/Finite-state_machine). |
| 10 | + |
| 11 | +## Background |
| 12 | + |
| 13 | +I have used variations of Stately in numerous iOS, macOS and .NET applications, and I've found it to be an invaluable tool. I created this open-source version of it for iOS, macOS, watchOS, and tvOS so that other people can both benefit from it and contribute to it. |
| 14 | + |
| 15 | +### Objective-C Compatibility |
| 16 | + |
| 17 | +At this time, Stately cannot be used with Objective-C projects. I decided that it makes the most sense to share Stately as a pure Swift framework. If it becomes clear that Objective-C compatibility is needed, I will add it. |
| 18 | + |
| 19 | +## Quick Links |
| 20 | + |
| 21 | +- [Getting Started](#getting-started) |
| 22 | +- [Basic Documentation](#basic-documentation) |
| 23 | +- [Example Project](#example-project) |
| 24 | +- [Contributing](#contributing) |
| 25 | +- [License](#license) |
| 26 | + |
| 27 | +## Getting Started |
| 28 | + |
| 29 | +Stately can be used via [Carthage](https://github.com/Carthage/Carthage). |
| 30 | + |
| 31 | +There are excellent [Insructions](https://github.com/Carthage/Carthage#getting-started) available on the [Carthage](https://github.com/Carthage/Carthage) site, which are summarized below. |
| 32 | + |
| 33 | +#### Add Stately to your Cartfile |
| 34 | + |
| 35 | +``` |
| 36 | +github "softwarenerd/Stately" |
| 37 | +``` |
| 38 | + |
| 39 | +#### Update Carthage |
| 40 | + |
| 41 | +```sh |
| 42 | +carthage update |
| 43 | +``` |
| 44 | + |
| 45 | +This will fetch dependencies into a `Carthage/Checkouts` folder, then build each one. |
| 46 | + |
| 47 | +#### Using Stately - macOS |
| 48 | + |
| 49 | +On your application targets’ “General” settings tab, in the “Embedded Binaries” section, drag and drop the Stately.framework file from the [Carthage/Build/Mac][] folder on disk. |
| 50 | + |
| 51 | +Additionally, you'll need to copy debug symbols for debugging and crash reporting on OS X. |
| 52 | + |
| 53 | +#### Using Stately - iOS, tvOS, watchOS |
| 54 | + |
| 55 | +1. On your application targets’ “General” settings tab, in the “Linked Frameworks and Libraries” section, drag and drop Stately.framework you want to use from the appropriate [Carthage/Build][] folder on disk. |
| 56 | +1. On your application targets’ “Build Phases” settings tab, click the “+” icon and choose “New Run Script Phase”. Create a Run Script in which you specify your shell (ex: `bin/sh`), add the following contents to the script area below the shell: |
| 57 | + |
| 58 | + ```sh |
| 59 | + /usr/local/bin/carthage copy-frameworks |
| 60 | + ``` |
| 61 | + |
| 62 | + and add the paths to the frameworks you want to use under “Input Files”, e.g.: |
| 63 | + |
| 64 | + ``` |
| 65 | + $(SRCROOT)/Carthage/Build/iOS/Stately.framework |
| 66 | + ``` |
| 67 | + |
| 68 | + This script works around an [App Store submission bug](http://www.openradar.me/radar?id=6409498411401216) triggered by universal binaries and ensures that necessary bitcode-related files and dSYMs are copied when archiving. |
| 69 | + |
| 70 | +With the debug information copied into the built products directory, Xcode will be able to symbolicate the stack trace whenever you stop at a breakpoint. |
| 71 | + |
| 72 | +When archiving your application for submission to the App Store or TestFlight, Xcode will also copy these files into the dSYMs subdirectory of your application’s `.xcarchive` bundle. |
| 73 | + |
| 74 | +## Basic Documentation |
| 75 | + |
| 76 | +Using [Stately](https://github.com/softwarenerd/Stately) is easy and straightforward. |
| 77 | + |
| 78 | +```swift |
| 79 | +var stateClosed: State! |
| 80 | +var stateOpened: State! |
| 81 | +var eventOpen: Event! |
| 82 | +var eventClose: Event! |
| 83 | +var stateMachine: StateMachine! |
| 84 | + |
| 85 | +do { |
| 86 | + // Define the states that the state machine can be in. |
| 87 | + stateClosed = try State(name: "Closed") { (object: AnyObject?) -> StateChange? in |
| 88 | + // Log. |
| 89 | + print("Closed") |
| 90 | + |
| 91 | + // Return, leaving state unchanged. |
| 92 | + return nil |
| 93 | + } |
| 94 | + stateOpened = try State(name: "Opened") { (object: AnyObject?) -> StateChange? in |
| 95 | + // Log. |
| 96 | + print("Opened") |
| 97 | + |
| 98 | + // Return, leaving state unchanged. |
| 99 | + return nil |
| 100 | + } |
| 101 | + |
| 102 | + // Define the events that can be sent to the state machine. |
| 103 | + eventOpen = try Event(name: "Open", transitions: [(fromState: stateClosed, toState: stateOpened)]) |
| 104 | + eventClose = try Event(name: "Close", transitions: [(fromState: stateOpened, toState: stateClosed)]) |
| 105 | + |
| 106 | + // Initialize the state machine. |
| 107 | + stateMachine = try StateMachine(name: "Door", |
| 108 | + defaultState: stateClosed, |
| 109 | + states: [stateClosed, stateOpened], |
| 110 | + events: [eventClose, eventOpen]) |
| 111 | + |
| 112 | + // Fire events to the state machine. |
| 113 | + stateMachine.fireEvent(event: eventOpen) |
| 114 | + stateMachine.fireEvent(event: eventClose) |
| 115 | +} catch { |
| 116 | + // Handle errors. |
| 117 | +} |
| 118 | +``` |
| 119 | + |
| 120 | +## Example Project |
| 121 | + |
| 122 | +The [StatelyExample](https://github.com/softwarenerd/StatelyExample) project provides a comprehensive example of using Stately to build a garage door simulator. |
| 123 | + |
| 124 | +## Contributing |
| 125 | + |
| 126 | +Stately is a work in progress and your contributions are most welcome. Feel free to fork the repo and submit PR's. |
| 127 | + |
| 128 | +## License |
| 129 | + |
| 130 | +Stately is released under the [MIT License](LICENSE.md). |
0 commit comments