Latest 0.0.8
License MIT
Platforms ios 8.0, requires ARC

Fisticuffs is a data binding framework for Swift, inspired by Knockout and shares many of the same concepts:

  • Declarative Bindings

    Simplify your view controllers by setting up all your view logic in one place. No need to implement target-actions, delegate methods, etc.

  • Automatic Updates

    When your data changes, your UI is automatically updated to reflect those changes. Likewise, when your users interact with your UI, your data is automatically updated.

  • Automatic Dependency Tracking

    Easily and implicitly setup a graph of dependencies. When an underlying dependency changes its value, Fisticuffs will ensure those changes are propagated up.

⚠️ NOTE: Fisticuffs is still alpha/beta. Hopefully the public interface won’t change much, but no guarantees until version 1.0

Quick Example

Since a code snippet can be worth a thousand words…

class LoginViewController: UIViewController {
  @IBOutlet var usernameField: UITextField!
  @IBOutlet var passwordField: UITextField!
  @IBOutlet var loginButton: UIButton!

  let username = Observable("")
  let password = Observable("")

  lazy var inputIsValid: Computed<Bool> = Computed { [weak self] in
    let user = self?.username.value
    let pass = self?.password.value
    return user?.isEmpty == false && pass?.isEmpty == false

  override viewDidLoad() {

    // bind the text in our username & password fields to their 

    // only enable the login button if they've entered an username and password

    // do the login when the user taps the login button 
    loginButton.b_onTap.subscribe { [weak self] in
      LoginManager.doLogin(self?.username.value, self?.password.value)

Core Concepts


The Observable class is one of the basic building blocks of Fisticuffs. It stores a value and notifies any subscribers when it changes:

let observable = Observable<String>("")

observable.subscribe { oldValue, newValue in

observable.value = "Hello, world"
// prints "Hello, world"


Computed is the read-only sibling of Observable. It uses a closure to compute its value. Additionally, it automatically updates its value when any of its Observable (and Computed) dependencies change. For example:

let name = Observable<String>("")
let greeting: Computed<String> = Computed {
  return "Hello, " + name.value

greeting.subscribe { oldValue, newValue in

name.value = "world"
// prints "Hello, world" because the change to `name` is propagated up to `greeting`


Finally, the Event class provides support for broadcasting events to its subscribers. It shares a similar interface to Observable & Computed:

let event = Event<String>()

event.subscribe { _, str in
}"Hello, world")
// prints "Hello, world"


As a side note, Observable, Computed, and Event all inherit from Subscribable to provide a common interface to subscribing to changes/events.


BindingHandlers describe how a raw data value (ie Int, String, NSDate, etc..) should be applied to a property
(UILabel.text, UIImageView.image, etc..)

Some useful examples of what can be done with BindingHandlers:

  • BindingHandlers.loadImage() – enables binding a NSURL to a UIImage property
  • BindingHandlers.formatSalary() – formats a raw salary Int as a nice string (ie 100k)
  • BindingHandlers.autoupdatingTimeAgo() – enables binding a NSDate to a String property (ie. UILabel.text) that
    shows values like "5 minutes ago", etc.. (and automatically updates the displayed string as time passes)

Generally the raw value (ie a Double for fantasy points) should be bubbled up to the UI in the view model, so that it
can be formatted as need for that view.

UI Bindings

Property bindings

Many of the UIKit classes have been extended to allow binding their properties to Subscribables. These properties are generally to

UIKit Fisticuffs
UILabel.text UILabel.b_text
UITextField.text UITextField.b_text
UIButton.enabled UIButton.b_enabled
UISwitch.on UISwitch.b_on


To bind a Subscribable (ie: Observable, Computed, etc…) to these, the bind() method can be used.

let messageLabel: UILabel = ...
let message = Observable("")


UI events are exposed as Event‘s, making it easy to attach behaviour to controls. For example:

let button: UIButton = ...

button.b_onTap.subscribe {
  print("Pressed button!")

UITableViews / UICollectionViews

Fisticuffs provides support for easily binding data to UITableViews / UICollectionViews. See example below:

let tableView: UITableView = ...
let days = Observable(["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"])

tableView.registerClass(UITableViewCell.self forCellReuseIdentifier: "Cell")
tableView.b_configure(days) { config in
  config.useCell(reuseIdentifier: "Cell") { day, cell in
    cell.textLabel?.text = day

  config.allowsMoving = true   // let user reorder the days
  config.allowsDeletion = true   // let user delete days (good-bye Monday! :)

Some interesting things to note:

  • Since we set allowsMoving & allowsDeletion, users can move & delete rows. The underlying data (days) will be updated automatically
  • Any updates we make to days in code will be propagated up to the table view (including animating insertions, removals, etc..)

Similar bindings exist for UICollectionView



  • Xcode 10 / Swift 4.2
  • iOS 8+


  1. If you haven’t already, install CocoaPods and setup your project for use with CocoaPods

  2. Add Fisticuffs to your Podfile:

    pod 'Fisticuffs', '0.0.8'
  3. Run pod install

NOTE: There may be breaking changes before 1.0, so it is suggested to pin it to a specific version


  1. If you haven’t already, install Carthage & setup your project for use with it. See here.

  2. Add Fisticuffs to your Cartfile:

    github "scoremedia/Fisticuffs" == 0.0.8
  3. Run carthage update

May be breaking changes before 1.0, so it is suggested to pin it to a specific version

Manual Installation

  1. Download this repository (if using Git, you can add it as a submodule)

  2. Drag Fisticuffs.xcodeproj into your Xcode project or workspace

  3. Add Fisticuffs.framework to your app’s Embedded Binaries and Linked Frameworks and Libraries

Examples / Tests

Tests and some examples are provided in the Fisticuffs.xcworkspace

Running the Tests

  1. Clone this repo

  2. To fetch Quick and Nimble, run:

    git submodule update --init --recursive
  3. Open Fisticuffs.xcworkspace, select the Fisticuffs scheme

  4. ProductTest


Fisticuffs is released under the MIT license.

Latest podspec

    "name": "Fisticuffs",
    "version": "0.0.8",
    "summary": "Fisticuffs is a data binding framework for Swift, inspired by Knockout.",
    "description": "Fisticuffs is a data binding framework for Swift, inspired by Knockout. Some of the features include:nn- Declarative Bindings to most UIKit controlsn- Automatic Updatesn- Automatic Dependency tracking",
    "homepage": "",
    "license": "MIT",
    "authors": {
        "Darren Clark": "[email protected]"
    "source": {
        "git": "",
        "tag": "0.0.8"
    "platforms": {
        "ios": "8.0"
    "swift_version": "4.2",
    "requires_arc": true,
    "source_files": "Source/**/*.{m,swift}"

Pin It on Pinterest

Share This