ASTableNode
ASTableNode
is equivalent to UIKit’s UITableView
and can be used in place of any UITableView
.
ASTableNode
replaces UITableView
’s required method
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
with your choice of one of the following methods
- (ASCellNode *)tableNode:(ASTableNode *)tableNode nodeForRowAtIndexPath:(NSIndexPath *)indexPath
or
- (ASCellNodeBlock)tableNode:(ASTableNode *)tableNode nodeBlockForRowAtIndexPath:(NSIndexPath *)indexPath
These two methods, need to return either an ASCellNode
or an ASCellNodeBlock
. An ASCellNodeBlock
is a block that creates a ASCellNode
which can be run on a background thread. Note that ASCellNodes
are used by ASTableNode
, ASCollectionNode
and ASPagerNode
.
Note that neither of these methods require a reuse mechanism.
Replacing UITableViewController with ASDKViewController
Texture does not offer an equivalent to UITableViewController
. Instead, use an ASDKViewController
initialized with an ASTableNode
.
Consider, again, the ASDKViewController
subclass - PhotoFeedNodeController - from the ASDKgram sample app
that uses a table node as its managed node.
An ASTableNode
is assigned to be managed by an ASDKViewController
in its -initWithNode:
designated initializer method.
- (instancetype)init
{
_tableNode = [[ASTableNode alloc] initWithStyle:UITableViewStylePlain];
self = [super initWithNode:_tableNode];
if (self) {
_tableNode.dataSource = self;
_tableNode.delegate = self;
}
return self;
}
Node Block Thread Safety Warning
It is very important that node blocks be thread-safe. One aspect of that is ensuring that the data model is accessed outside of the node block. Therefore, it is unlikely that you should need to use the index inside of the block.
Consider the following -tableNode:nodeBlockForRowAtIndexPath:
method from the PhotoFeedNodeController.m
file in the ASDKgram sample app.
- (ASCellNodeBlock)tableNode:(ASTableNode *)tableNode nodeBlockForRowAtIndexPath:(NSIndexPath *)indexPath
{
PhotoModel *photoModel = [_photoFeed objectAtIndex:indexPath.row];
// this may be executed on a background thread - it is important to make sure it is thread safe
ASCellNode *(^cellNodeBlock)() = ^ASCellNode *() {
PhotoCellNode *cellNode = [[PhotoCellNode alloc] initWithPhoto:photoModel];
cellNode.delegate = self;
return cellNode;
};
return cellNodeBlock;
}
In the example above, you can see how the index is used to access the photo model before creating the node block.
Accessing the ASTableView
If you’ve used previous versions of Texture, you’ll notice that ASTableView
has been removed in favor of ASTableNode
.
ASTableView
, an actual UITableView
subclass, is still used internally by ASTableNode
. While it should not be created directly, it can still be used directly by accessing the .view
property of an ASTableNode
.
Don't forget that a node's view
or layer
property should only be accessed after -viewDidLoad
or -didLoad
, respectively, have been called.
For example, you may want to set a table’s separator style property. This can be done by accessing the table node’s view in the -viewDidLoad:
method as seen in the example below.
- (void)viewDidLoad
{
[super viewDidLoad];
_tableNode.view.allowsSelection = NO;
_tableNode.view.separatorStyle = UITableViewCellSeparatorStyleNone;
_tableNode.view.leadingScreensForBatching = 3.0; // default is 2.0
}
Table Row Height
An important thing to notice is that ASTableNode
does not provide an equivalent to UITableView
’s -tableView:heightForRowAtIndexPath:
.
This is because nodes are responsible for determining their own height based on the provided constraints. This means you no longer have to write code to determine this detail at the view controller level.
A node defines its height by way of the layoutSpec returned in the -layoutSpecThatFits:
method. All nodes given a constrained size are able to calculate their desired size.
ASTableNode
provides its cells with a size range constraint where the minimum width is the tableNode's width and a minimum height is 0
. The maximum width is also the tableNode
's width but the maximum height is FLT_MAX
.
This is all to say, a `tableNode`'s cells will always fill the full width of the `tableNode`, but their height is flexible making self-sizing cells something that happens automatically.
If you call -setNeedsLayout
on an ASCellNode
, it will automatically perform another layout pass and if its overall desired size has changed, the table will be informed and will update itself.
This is different from UIKit
where normally you would have to call reload row / item. This saves tons of code, check out the ASDKgram sample app to see side by side implementations of an UITableView
and ASTableNode
implemented social media feed.
Sample Apps using ASTableNode
- ASDKgram
- Kittens
- HorizontalWithinVerticalScrolling
- VerticalWithinHorizontalScrolling
- SocialAppLayout