--- title: "ASNodeController (Beta)" layout: docs permalink: /docs/containers-asnodecontroller.html prevPage: containers-asviewcontroller.html nextPage: containers-astablenode.html ---
To use this feature, you will need to import "ASNodeController+Beta.h"
The Texture team has many exciting ideas for expanding `ASNodeController`. Follow along [here](https://github.com/facebook/AsyncDisplayKit/issues/2964) if you'd like to participate in shaping the future of node controllers. For now, `ASNodeController` remains a simple, but powerful class. ### Example The [example project](https://github.com/texturegroup/texture/pull/2945) attached in the initial PR modifies the normal [ASDKgram](https://github.com/texturegroup/texture/tree/master/examples/ASDKgram) project to use an `ASNodeController`. This `PhotoCellNodeController` is used to manage the fetching of the comments data for a photo in a photo feed, once the photo enters the preload range. This node controller allows us to separate the preloading logic from where it previously existed in the `PhotoCellNode` "view" class. To convert ASDKgram to use an `ASNodeController`, we first create a `PhotoCellNodeController` class. This node controller overrides `ASNodeController`'s' `-loadNode` method to create a `PhotoCellNode` once required. It is not neccessary to call super in this method. This node controller also observes its node's interface state in order to intelligently preload the photo's comment feed model data when the `PhotoCellNode` enters the preload state (which indicates that the photo cell is likely to scroll onscreen soon). All of this logic can be removed from where it previously existed in the "view" (our `PhotoCellNode` class), leading to a more concise and MVC-friendly view class.
Swift Objective-C
@implementation PhotoCellNodeController

- (void)loadNode
{
  self.node = [[PhotoCellNode alloc] initWithPhotoObject:self.photoModel];
}

- (void)didEnterPreloadState
{
  [super didEnterPreloadState];
  
  CommentFeedModel *commentFeedModel = _photoModel.commentFeed;
  [commentFeedModel refreshFeedWithCompletionBlock:^(NSArray *newComments) {
    // load comments for photo
    if (commentFeedModel.numberOfItemsInFeed > 0) {
      [self.node.photoCommentsNode updateWithCommentFeedModel:commentFeedModel];
      [self.node setNeedsLayout];
    }
  }];
}

@end
  
Next, we add a mutable array to the `PhotoFeedNodeController` to store our node controllers and instantiate it in the init method.
Swift Objective-C
@implementation PhotoFeedNodeController
{
  PhotoFeedModel          *_photoFeed;
  ASTableNode             *_tableNode;
  NSMutableArray *_photoCellNodeControllers;
}

- (instancetype)init
{
  _tableNode = [[ASTableNode alloc] init];
  self = [super initWithNode:_tableNode];
  
  if (self) {
    self.navigationItem.title = @"Texture";
    [self.navigationController setNavigationBarHidden:YES];
    
    _tableNode.dataSource = self;
    _tableNode.delegate = self;
    
    _photoCellNodeControllers = [NSMutableArray array];
  }
  
  return self;
}
  
To use this node controller, we modify our table row insertion logic to create a `PhotoCellNodeController` rather than a `PhotoCellNode` directly and add it to our node controller array.
Swift Objective-C
- (void)insertNewRowsInTableNode:(NSArray *)newPhotos
{
  NSInteger section = 0;
  NSMutableArray *indexPaths = [NSMutableArray array];
  
  NSUInteger newTotalNumberOfPhotos = [_photoFeed numberOfItemsInFeed];
  for (NSUInteger row = newTotalNumberOfPhotos - newPhotos.count; row < newTotalNumberOfPhotos; row++) {
  
    // create photoCellNodeControllers for the new photos
    PhotoCellNodeController *cellController = [[PhotoCellNodeController alloc] init];
    cellController.photoModel = [_photoFeed objectAtIndex:row];
    [_photoCellNodeControllers addObject:cellController];
    
    // include this index path in the insert rows call for the table
    NSIndexPath *path = [NSIndexPath indexPathForRow:row inSection:section];
    [indexPaths addObject:path];
  }
  
  [_tableNode insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationNone];
}
  
Don't forget to modify the table data source method to return the node controller rather than the cell node.
Swift Objective-C
- (ASCellNodeBlock)tableNode:(ASTableNode *)tableNode nodeBlockForRowAtIndexPath:(NSIndexPath *)indexPath
{
  PhotoCellNodeController *cellController = [_photoCellNodeControllers objectAtIndex:indexPath.row];
  // this will be executed on a background thread - important to make sure it's thread safe
  ASCellNode *(^ASCellNodeBlock)() = ^ASCellNode *() {
    PhotoCellNode *cellNode = [cellController node];
    return cellNode;
  };
  
  return ASCellNodeBlock;
}