Swiftgram/AsyncDisplayKit/ASCellNode.m
Nadine Salter 7dd94a6102 Merge in downstream changes.
Introduce `ASTableView`, a UITableView subclass that uses `ASCellNode`
instead of UITableViewCell.  Add working range support via
`ASRangeController`, which observes the visible range, maintains a
working range, and handles most ASDK machinery.  ASRangeController is
loosely-enough coupled that it should be easily adapted to
UICollectionView if that's desired in the future.

Notable considerations in the ASRangeController architecture:

* There's no sense rewriting UITableView -- the real win comes from
  using nodes instead of UITableViewCells (easily parallelisable
  computation, large number of cells vs. few table views, etc.).  So,
  use a UITableView with empty cells, using UITableViewCell's
  contentView as a host for arbitrary node hierarchies.

* Instead of lazy-loading cells the instant they're needed by
  UITableView, load them in advance.  Preload a substantial number of
  nodes in the direction of scroll, as well as a small buffer in the
  other direction.

* Maintain compatibility with UITableView's API, with one primary change
  -- consumer code yields configured ASCellNodes, not UITableViewCells.

* Don't use -tableView:heightForRowAtIndexPath:.  Nodes already compute
  their preferred sizes and cache results for use at layout-time, so
  ASTableView uses their calculatedSizes directly.

* Corollary:  ASTableView is only aware of nodes that have been sized.
  This means that, if a cell appears onscreen, it has layout data and
  can display a "realistic placeholder", e.g. by making its subnodes'
  background colour grey.

Other improvements:

* Remove dead references and update headers (fixes #7, #20).

* Rename `-[ASDisplayNode sizeToFit:]` to `-measure:` and fix
  `constrainedSizeForCalulatedSize` typo (fixes #15).

* Rename `-willAppear` and `-didDisappear` to `-willEnterHierarchy` and
  `-didExitHierarchy`.  Remove `-willDisappear` -- it was redundant, and
  there was no counterpart `-didAppear`.

* Rename `viewLoaded` to `nodeLoaded`.
2014-09-22 14:33:39 -07:00

110 lines
2.4 KiB
Objective-C

/* Copyright (c) 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import "ASCellNode.h"
#import "ASDisplayNode+Subclasses.h"
#import "ASRangeControllerInternal.h"
#import "ASTextNode.h"
#pragma mark -
#pragma mark ASCellNode
@interface ASCellNode () {
// used by ASRangeController machinery
NSIndexPath *_asyncdisplaykit_indexPath;
}
@end
@implementation ASCellNode
- (instancetype)init
{
if (!(self = [super init]))
return nil;
return self;
}
// TODO consider making this property an associated object in ASRangeController.mm
- (NSIndexPath *)asyncdisplaykit_indexPath
{
return _asyncdisplaykit_indexPath;
}
- (void)setAsyncdisplaykit_indexPath:(NSIndexPath *)asyncdisplaykit_indexPath
{
if (_asyncdisplaykit_indexPath == asyncdisplaykit_indexPath)
return;
_asyncdisplaykit_indexPath = [asyncdisplaykit_indexPath copy];
}
@end
#pragma mark -
#pragma mark ASTextCellNode
@interface ASTextCellNode () {
NSString *_text;
ASTextNode *_textNode;
}
@end
@implementation ASTextCellNode
static const CGFloat kHorizontalPadding = 15.0f;
static const CGFloat kVerticalPadding = 11.0f;
static const CGFloat kFontSize = 18.0f;
- (instancetype)init
{
if (!(self = [super init]))
return nil;
_textNode = [[ASTextNode alloc] init];
[self addSubnode:_textNode];
return self;
}
- (CGSize)calculateSizeThatFits:(CGSize)constrainedSize
{
CGSize availableSize = CGSizeMake(constrainedSize.width - 2 * kHorizontalPadding,
constrainedSize.height - 2 * kVerticalPadding);
CGSize textNodeSize = [_textNode measure:availableSize];
return CGSizeMake(ceilf(2 * kHorizontalPadding + textNodeSize.width),
ceilf(2 * kVerticalPadding + textNodeSize.height));
}
- (void)layout
{
_textNode.frame = CGRectInset(self.bounds, kHorizontalPadding, kVerticalPadding);
}
- (void)setText:(NSString *)text
{
if (_text == text)
return;
_text = [text copy];
_textNode.attributedString = [[NSAttributedString alloc] initWithString:_text
attributes:@{NSFontAttributeName: [UIFont systemFontOfSize:kFontSize]}];
[self invalidateCalculatedSize];
}
@end