I am not going to maintain this project anymore because it doesn't fit well into the Swift landscape and Swift is taking over the iOS community much faster than I have anticipated.
Swift-UI makes this approach obsolete.
AKA Beacon is a data binding framework for iOS designed for Interface Builder.
- What is Data Binding
- About View Models
- What are the advantages of using Data Binding
- How is Beacon different from Data Binding on OS X
- How does Beacon relate to other binding frameworks
Version 0.3.1
- Fixes related to Cocoapods 1.0, pod try
- Fixes in Demo App
Version 0.3
- Removed dependencies to AKACommons (merged) and CocoaLumberjack (temporarily until modular podspec is done).
- Support for conditional binding expressions ($when, $whenNot, $else)
- Refactored UITableView data source binding to use conditionals in cell mappings
- Installation & Integration
- License (BSD 2-clause license)
- Getting Started
- Documentation
- How Beacon works
- Examples
Beacon is available on CocoaPods.
To integrate AKABeacon, enable use_frameworks!
in your Podfile and add the dependency to AKABeacon:
use_frameworks!
...
pod 'AKABeacon', '~> 0.3'
If you are using the CocoaPods try plugin, an easy way to start experimenting with Beacon is:
$ pod try AKABeacon
BSD 2-clause, see LICENSE.txt
Once you integrated the framework into your project, all you have to do to use bindings is:
- Design your view hierarchies in Storyboards or NIB files the same way you did before.
- Define binding expressions in the property inspector for your views. For example, to bind a text field or label text to a property
myTextProperty
, simply set the "Text Binding" property tomyTextProperty
.
- Enable binding support in your view controller. To do that, add
[AKABindingBehavior addToViewController:self]
to your ViewController'sviewDidLoad
method (You need to@import AKABeacon;
). - Your view controller is (by default) used as root view model, so it has to provide the properties for key paths you use in your binding expressions. For the example above, the binding would expect the view controller to implement a key value coding-compliant property
myTextProperty
.
The demo project contains a lot of examples for different binding types.
- Beacon's Github Wiki
- The API documentation is still not in a usable state, mainly because the code base is not yet sufficiently stable. Stay tuned.
- The most up to date information is available here (, Luke)
The typical usage scenario is (what you do - that's the yellow bubbles in the diagram below):
- You add the beacon framework to your project. From then on, you will find additional properties for views and view controllers in Interface Builder's property panel.
- You enable binding support for your view controller, which is implemented by adding a binding behavior as child view controller.
- Your view controller provides properties or a reference to your model data
- You design a view in Interface Builder and assign binding expressions to views which should be bound to your data.
What happens behind the scenes (Beacon's job, everything that's blue in the diagram):
- When you enable binding support, beacon adds a binding behavior as child view controller to yours. This behavior receives life cycle events along with your own controller:
- viewDidLoad: The binding behavior will inspect your view hierarchy to find views defining binding expressions and create bindings for them.
- viewWillAppear: The bindings will initialize views with content from your view model observe changes on boths ends and perform the necessary updates.
- viewWillDisappear: Bindings will stop observing changes.
Many of these tasks are actually carried out by controls which are in charge of managing bindings, providing data contexts and controlling the behavior of view hierarchies. In most cases you can ignore controls, since they do their job transparently without bothering you. If you need to interact with them however, they provide fine granular delegate methods, which you can use to inspect and control the behavior of controls and bindings. Your view controller is automatically used as AKABindingBehaviorDelegate if you conform to that protocol.
Please note that most modules in Beacon are designed to be independent. You can for example use bindings without controls, and you don't have to use form view controllers to manage controls and bindings.
We spend a lot of effort to ensure that you can use the parts of the framework that actually help you without requiring you to put your architecture upside down just to integrate data binding functionality.
We also tried hard to take over all the work to support standard use cases such that you don't have to write code, just to make sure that your text fields are visible when you're typing, that it still works when you rotate the device. This is going much further than scrolling. In later versions you will get automatic support for theming, automatic font resizing, highlighting of search terms, form transaction support (model values are updated at the end of a form editing session and only if valid) and much more.
Note: The examples here are aging, take a look at the demo application for up to date impressions.
The following screen shot shows a view with three text fields. The first two are bound to a property stringValue
, the first text field will update the data source after each key stroke, the second when the text field will lose keyboard focus.
The third text field is bound to a number value and demonstrates different editing and display number formatters.
stringValue {
textForUndefinedValue: "(Please enter some text)",
treatEmptyTextAsUndefined: $true
}
stringValue { liveModelUpdates: $false }
numberValue {
numberFormatter: {
numberStyle: $enum.CurrencyStyle
},
editingNumberFormatter: {
maximumFractionDigits: 5
}
}
Picker keyboard trigger views wrap content and react to a tap gesture by opening up a keyboard containing a picker view. This example shows two such trigger views. The first is set up to choose a string from an array of strings and contains a label that is bound to the selected value. The second trigger view selects an object from an array of objects (displaying the title property as choice title).
The binding expressions used here are:
Label: (connects the label to key path stringValue
and configures the binding to display "(tap to choose)" if the value is undefined).
stringValue {
textForUndefinedValue: "(tap to choose)"
}
Picker: (the picker keyboard takes its choices from stringArrayValue
. Since no title is specified, array items will be used as values for respective choices).
stringValue {
choices: stringArrayValue,
titleForUndefinedValue: "(please choose)"
}
Labels: (This picker contains multiple labels bound to different properties of the data context, which is an object in this case).
objectValue.title
objectValue.value
Picker: (Here, the array items are complex objects, so the title attribute is defined as key path relative to the respective array item; picker keyboards also support the setting liveModelUpdates).
objectValue {
title: title,
choices: objectArrayValue,
liveModelUpdates: $false
}
Date picker label: (See the section on label formatting).
dateValue { dateFormatter: { dateStyle: $enum.LongStyle, timeStyle: $enum.MediumStyle } }
Picker: (The date picker only needs the key path for the selected value).
dateValue
The following examples demonstrate the built-in formatting capabilities of Beacon. Beacon uses NSFormatter as interface for formatting and NSNumberFormatter and NSDateFormatter for numbers and dates respectively. You can define custom formatters other types.
The numberFormatter attribute supports most configuration properties of NSNumberFormatter. Enumeration values can be specified as $enum.Value
(if the enumeration is known to Beacon) or $enum.Type.Value
(you can provide mappings for your own enumerations).
floatValue {
numberFormatter: {
numberStyle: $enum.CurrencyStyle
}
}
textForYes and textForNo allow you to map number values to title.
boolValue {
textForYes: "Yes",
textForNo: "No"
}
If you don't need any formatting, just specifying the key path to the value is enough.
textValue
You can use your own formatters by specifying the class name in angle brackets. You are however restricted by the data types that can be represented as binding expressions for the configuration of your custom formatter. As mentioned above, enumerations values can be registered:
objectValue {
formatter: <CustomFormatter> {
format: "Hello, %@"
}
}
We're planning to support templating libraries such as mustache or handlebars. Once implemented a similar example would look like:
objectValue {
formatter: <MustacheFormatter> {
template: "Hello, {{givenName}} {{familyName}}"
}
}
Similar to number values, date values can be formatter using the NSDateFormatter.
dateValue {
dateFormatter: {
dateStyle: $enum.NSDateFormatterStyle.LongStyle,
timeStyle: $enum.LongStyle
}
}