Nimbus
0.9.3 - Nimbus is proudly hosted on Github
An iOS framework whose growth is bounded by O(documentation).
|
A table cell factory automatically creates UITableViewCells from objects.
The Nimbus table cell factory works by requiring that objects implement a basic protocol, NICellObject, which sets up a binding from the object to a specific cell implementation. This cell implementation can optionally implement the NICell protocol. In practice this is nearly always the case. You then simply use the factory in your table's data source and the factory will handle the rest. This allows you to completely separate presentation from data in your table view controllers.
Let's say you want to build a Twitter news feed. We'll assume you've already figured out the network requests and now have individual tweets itching to be displayed. To use the Nimbus factory you will need two different classes: one for the tweet object and its data, and another for the tweet table view cell. Let's call them Tweet and TweetCell, respectively. You may even already have a Tweet object.
You must first implement the NICellObject protocol in your Tweet object. We want to link the TweetCell table view cell to the Tweet object so that the factory can create a TweetCell when it needs to present the Tweet object.
@interface Tweet : NSObject <NICellObject> { // ... } @end @implementation Tweet - (Class)cellClass { return [TweetCell class]; } @end
Now that we've pointed the Tweet object to the TweetCell class, let's make the table controller use the NICellFactory.
There are a few ways you can use the factory in your code. We'll walk through increasingly Nimbus-like implementations, starting with a vanilla UIKit implementation.
The following vanilla UIKit implementation has the advantage of allowing you to use NICellFactory in your existing code base without requiring a full rewrite of your data source. If you are attempting to switch to a pure Nimbus implementation using the cell factory then this is a good first step because it is the least invasive.
- (UITableViewCell *)tableView: (UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath { // Note: You must fetch the object at this index path somehow. The objectAtIndexPath: // is simply an example; replace it with your own implementation. id object = [self objectAtIndexPath:indexPath]; UITableViewCell* cell = [NICellFactory tableViewModel:nil cellForTableView:tableView atIndexPath:indexPath withObject:object]; if (nil == cell) { // Here would be whatever code you were originally using to create cells. nil is only returned // when the factory wasn't able to create a cell, likely due to the NICellObject protocol // not being implemented for the given object. As you implement these protocols on // more objects the factory will automatically start returning the correct cells // and you can start removing this special-case logic. } return cell; }
This next implementation is what your vanilla data source implementation would look like once you have no more custom cell creation code.
- (UITableViewCell *)tableView: (UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath { // Note: You must fetch the object at this index path somehow. The objectAtIndexPath: // is simply an example; replace it with your own implementation. id object = [self objectAtIndexPath:indexPath]; // Only use the factory to create cells now that every object used in this controller // implements the factory protocols. return [NICellFactory tableViewModel:nil cellForTableView:tableView atIndexPath:indexPath withObject:object]; }
If you are using Nimbus models then your code gets even simpler because the object is passed to your model delegate method.
- (UITableViewCell *)tableViewModel: (NITableViewModel *)tableViewModel cellForTableView: (UITableView *)tableView atIndexPath: (NSIndexPath *)indexPath withObject: (id)object { // The model gives us the object, making this much simpler and likely more efficient than the vanilla UIKit implementation. return [NICellFactory tableViewModel:tableViewModel cellForTableView:tableView atIndexPath:indexPath withObject:object]; }
And finally, if you require no custom code in your model delegate, the above example can be shortened to a one-liner when you initialize the model:
// This is functionally identical to implementing the delegate in this controller and simply // calling the factory method. _model.delegate = (id)[NICellFactory class];
We want to customize the cells as they are presented, otherwise all of the cells will look the same. After our TweetCell object is created in the factory, the factory will call the shouldUpdateCellWithObject: method on the cell, if it is implemented. Remember that cells are reused in table views and that any modification you may make to the cell could still be present the next time this cell is updated with an object.
- (BOOL)shouldUpdateCellWithObject:(id)object { // We can be rest assured that `object` is a Tweet object because that's how we set up // the bindings. If more than one type of object maps to this cell class then we'd have // to check the object type accordingly. Tweet* tweet = object; self.textLabel.text = tweet.text; // Returning YES or NO here is intended purely for subclassing purposes. Returning YES means // that the object changed the cell in some way. return YES; }
The Nimbus cell factory can greatly reduce the amount of code you have to write in your table controllers while separating the data from the presentation. You can slowly ease yourself into using the factory if you already have a large existing code base.
If you are migrating from Three20, you will find that Nimbus' table factory is very similar to TTTableViewController, though greatly simplified and decoupled from the rest of the Three20 ecosystem. Where Three20 provided a tightly integrated solution, Nimbus allows you to plug in the factory where it makes sense.
Classes | |
class | NICellFactory |
A simple factory for creating table view cells from objects. More... | |
protocol | <NICellObject> |
The protocol for an object that can be used in the NICellFactory. More... | |
protocol | <NICell> |
The protocol for a cell created in the NICellFactory. More... |